Python中线程未持有锁为何能释放?有序打印代码锁疑问
LeetCode有序打印问题的锁同步疑惑解答
问题背景
我在解决LeetCode的有序打印问题时,用Lock做线程同步,代码能正常运行,但有个疑惑:
代码实现
from threading import Lock, current_thread from concurrent import futures from typing import Callable class Foo: def __init__(self): self.first_lock = Lock() self.second_lock = Lock() self.first_lock.acquire() self.second_lock.acquire() print(f'{current_thread()} in __init__') def first(self, printFirst: Callable[[], None]) -> None: print(f'{current_thread()} in first') printFirst() self.first_lock.release() def second(self, printSecond: Callable[[], None]) -> None: print(f'{current_thread()} in second') with self.first_lock: printSecond() self.second_lock.release() def third(self, printThird: Callable[[], None]) -> None: print(f'{current_thread()} in third') with self.second_lock: printThird() def printFirst(): print("First") def printSecond(): print("Second") def printThird(): print("Third") foo = Foo() with futures.ThreadPoolExecutor(max_workers=3) as executor: to_do: list[futures.Future] = [] to_do.append(executor.submit(foo.third, printThird)) to_do.append(executor.submit(foo.second, printSecond)) to_do.append(executor.submit(foo.first, printFirst)) print("all set?")
疑问
foo在主线程中实例化,所以主线程持有这两个锁?如果是这样,主线程从未释放锁,为什么执行first方法的其他线程可以释放该锁?
解答
核心原因是:Python标准库的threading.Lock不与特定线程绑定。
具体说明:
threading.Lock只关注自身的状态(锁定/未锁定),不校验调用release()的线程是否是之前调用acquire()的线程。只要当前锁处于锁定状态,任何线程调用release()都能将其解锁;只有当锁已经处于未锁定状态时调用release(),才会抛出RuntimeError。- 回到你的代码逻辑:
- 主线程在
Foo初始化时,通过acquire()将first_lock和second_lock置为锁定状态。 - 线程池中的
first线程执行self.first_lock.release(),直接解锁first_lock,无需考虑锁的持有者是主线程。 - 解锁后
second线程的with self.first_lock能成功获取锁,执行完打印逻辑后调用self.second_lock.release()解锁第二个锁,最后third线程通过with self.second_lock获取锁完成执行。
- 主线程在
需要注意:这种跨线程释放锁的写法属于利用Python Lock的实现特性,不符合锁的常规使用规范(通常要求获取锁的线程负责释放锁)。更规范的实现可以用threading.Event或threading.Condition来明确控制执行顺序,逻辑会更清晰,也更符合多线程同步的最佳实践。
内容的提问来源于stack exchange,提问作者Aviral Srivastava
相关产品推荐
相关产品推荐

