admin管理员组文章数量:1599529
Python 中 Condition 的实现原理
- Condition 提供了实现一个生产者一个消费者情况下,非常方便的同步工具。Condition 怎么使用呢,一言不合上代码:
from threading import Thread,Condition,Lock
from time import sleep
from random import randint
def supplier(res_con, res_desk):
print("Supplier Started", flush=True)
# notify 前锁必须 acquire(),notify() 后必须 release() 才能让其他 wait() 返回
res_con.acquire()
while True:
res = randint(1, 100)
res_desk.append(res)
print("Supplier Data Ready: " + str(res), flush=True)
res_con.notify()
res_con.wait()
def nicotian(res_con, res_desk):
print("Nicotian Started", flush=True)
res_con.acquire()
while True:
# 进入时释放锁,然后阻塞,被唤醒后获取锁,然后返回
res_con.wait()
res = res_desk.pop()
sleep(1)
print("Nicotian Dealed Data: " + str(res), flush=True)
res_con.notify()
def main():
# 材料状态控制
res_con = Condition(Lock())
# 材料桌
res_desk = []
# 吸烟者,消费者线程应该先准备好等待
thread_nic = Thread(target=nicotian, args=(res_con, res_desk), daemon=True)
thread_nic.start()
sleep(1)
# 供应者
thread_supp = Thread(target=supplier, args=(res_con, res_desk), daemon=True)
thread_supp.start()
input("\n\n===Enter Any Key To Exit===\n\n")
if __name__ == '__main__':
main()
- 非常好奇
wait()
的逻辑进入时释放锁,然后阻塞,被唤醒后获取锁,然后返回是怎么实现的,明明只绑定了一个锁,阻塞如何实现的,被唤醒怎么实现的? - 原理:原来是维护了一个
_waiters
(这个不是服务员哦) 列表,在wait()
中连续wait.acquire()
两次,把自己阻塞;在调用notify()
后,选择其中一个waiter.release()
唤醒一个等待的线程。 - 真真是:一个锁连续 acquire 两次的应用场景(刚学 Python 语法的时候不是说这样会死锁吗,原来只是学的不够深入而已)
- 源码附上
def notify(self, n=1):
if not self._is_owned():
raise RuntimeError("cannot notify on un-acquired lock")
all_waiters = self._waiters
waiters_to_notify = _deque(_islice(all_waiters, n))
if not waiters_to_notify:
return
for waiter in waiters_to_notify:
waiter.release()
try:
all_waiters.remove(waiter)
except ValueError:
pass
def wait(self, timeout=None):
if not self._is_owned():
raise RuntimeError("cannot wait on un-acquired lock")
waiter = _allocate_lock() # 就是 Lock 本身
waiter.acquire()
self._waiters.append(waiter)
saved_state = self._release_save()
gotit = False
try: # restore state no matter what (e.g., KeyboardInterrupt)
if timeout is None:
waiter.acquire()
gotit = True
else:
if timeout > 0:
gotit = waiter.acquire(True, timeout)
else:
gotit = waiter.acquire(False)
return gotit
finally:
self._acquire_restore(saved_state)
if not gotit:
try:
self._waiters.remove(waiter)
except ValueError:
pass
版权声明:本文标题:Python 中 Condition 的实现原理(一个锁连续 acquire 两次的应用场景) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1728324286a1154230.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论