Python threading.Condition 源码解析:从底层锁机制到 wait/notify 流程
本文深入解析Python中threading.Condition的实现原理。Condition基于RLock构建,支持with上下文管理器。通过剖析wait和notify方法的源码,揭示其内部通过分配临时锁、维护等待队列(deque)以及释放与重新获取锁的机制,实现线程间的复杂同步协作,其逻辑类似于Java中的wait/notify。
Condition与Java wait/notify机制对比
通过观察上述示例代码,可以发现其执行逻辑与Java中线程通信的wait和notify机制高度相似,都是通过条件变量来控制线程的执行顺序。
import threading
# 条件变量,用于复杂的线程间同步锁
"""
需求:
男:小姐姐,你好呀!
女:哼,想泡老娘不成?
男:对呀,想泡你
女:滚蛋,门都没有!
男:切,长这么丑, 还这么吊...
女:关你鸟事!
"""
class Boy(threading.Thread):
def __init__(self, name, condition):
super().__init__(name=name)
self.condition = condition
def run(self):
with self.condition:
print("{}:小姐姐,你好呀!".format(self.name))
self.condition.wait()
self.condition.notify()
print("{}:对呀,想泡你".format(self.name))
self.condition.wait()
self.condition.notify()
print("{}:切,长这么丑, 还这么吊...".format(self.name))
self.condition.wait()
self.condition.notify()
class Girl(threading.Thread):
def __init__(self, name, condition):
super().__init__(name=name)
self.condition = condition
def run(self):
with self.condition:
print("{}:哼,想泡老娘不成?".format(self.name))
self.condition.notify()
self.condition.wait()
print("{}:滚蛋,门都没有!".format(self.name))
self.condition.notify()
self.condition.wait()
print("{}:关你鸟事!".format(self.name))
self.condition.notify()
self.condition.wait()
if __name__ == '__main__':
condition = threading.Condition()
boy_thread = Boy('男', condition)
girl_thread = Girl('女', condition)
boy_thread.start()
girl_thread.start()
Condition的上下文管理器支持
Condition类在底层实现了__enter__和__exit__协议,这意味着它可以直接作为上下文管理器使用,简化了锁的获取与释放操作。
底层锁机制:RLock的应用
从Condition的__init__初始化方法可以看出,其内部维护了一个RLock(可重入锁)作为底层锁机制,确保线程安全。
def __enter__(self):
return self._lock.__enter__()
def __exit__(self, *args):
return self._lock.__exit__(*args)
def __exit__(self, t, v, tb):
self.release()
def release(self):
"""Release a lock, decrementing the recursion level.
If after the decrement it is zero, reset the lock to unlocked (not owned
by any thread), and if any other threads are blocked waiting for the
lock to become unlocked, allow exactly one of them to proceed. If after
the decrement the recursion level is still nonzero, the lock remains
locked and owned by the calling thread.
Only call this method when the calling thread owns the lock. A
RuntimeError is raised if this method is called when the lock is
unlocked.
There is no return value.
"""
if self._owner != get_ident():
raise RuntimeError("cannot release un-acquired lock")
self._count = count = self._count - 1
if not count:
self._owner = None
self._block.release()
wait与notify源码深度解析
关于wait和notify方法的具体操作流程,理解起来可能存在一定难度,需要深入源码进行分析。
在wait()方法的源码中,主要包含以下关键步骤:
首先调用_allocate_lock()从底层分配一把新的锁,这并非标准的Lock锁;接着执行waiter.acquire()获取该锁;然后将这把锁添加到_waiters(一个deque双端队列)中;最后调用self._release_save()来释放__enter__时获取的那把锁。
接下来查看notify()方法的源码实现。
all_waiters = self._waiters
waiters_to_notify = _deque(_islice(all_waiters, n))# 从_waiters中取出n个
if not waiters_to_notify: # 如果是None,结束
return
for waiter in waiters_to_notify: # 循环release
waiter.release()
try:
all_waiters.remove(waiter) #从_waiters中移除
except ValueError:
pass
其核心逻辑可以概括为:wait方法先从底层创建锁,执行acquire操作,并将其放入deque队列中,随后释放with语句获取的锁;而notify方法执行时,从deque队列中取出锁并执行release操作,从而唤醒等待的线程。
以上就是本文对Python threading.Condition实现过程的完整解析,希望能为读者的学习提供参考,也欢迎大家继续支持本站获取更多技术内容。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













