首页 > 解决方案 > 为什么通知/释放 Condition 对象时我的线程没有启动备份?

问题描述

这个问题与 Python 3.6 有关。

我有一段代码运行线程库中的一个线程,以及程序的主线程。两个线程都访问一个不是线程安全的对象,所以我让它们在Condition使用对象之前锁定一个对象。我生成的线程只需要每 5 分钟访问/更新一次该对象,因此循环中有一个 5 分钟的睡眠计时器。

目前,主线程永远不会获得锁。当第二个线程释放Condition并开始等待sleep()调用时,主线程永远不会唤醒/获取锁。就好像主线程已经死了一样。

class Loader:
    def __init__(self, q):
        ...
        self.queryLock = threading.Condition()
        ...
        thread = Thread(target=self.threadfunc, daemon=True)
        thread.start()
        ...
        self.run()

    def threadfunc(self):
        ...
        while True:
            self.queryLock.acquire()
            [critical section #1]
            self.queryLock.notify()
            self.queryLock.release()
            sleep(300)

    def run(self):
        ...
        while True:
            ...
            self.queryLock.acquire()
            [critical section #2]
            self.queryLock.notify()
            self.queryLock.release()
            ...

标签: pythonmultithreadingthread-safetypython-3.6

解决方案


I believe you don't really need to use a Condition. It appears that a simple Lock would get the job done in your case. You don't actually verify that some condition is met and you don't use the Condition's special method wait().


That being said, regarding the code you provided, it seems that your main thread is too "quick", and re-acquires the lock before the other thread gets a chance. Here is a slightly modified version of your code in which the main thread is waiting a bit, giving the other thread a chance, and it successfully acquires the lock and continue.

class Loader:
    def __init__(self):
        self.queryLock = threading.Condition()
        thread = Thread(target=self.threadfunc, daemon=True)
        thread.start()
        self.run()
    
    def threadfunc(self):
        while True:
            self.queryLock.acquire()
            print("critical section 1")
            time.sleep(1)
            self.queryLock.notify()
            self.queryLock.release()
            time.sleep(5)
    
    def run(self):
        while True:
            self.queryLock.acquire()
            print("critical section 2")
            time.sleep(2)
            self.queryLock.notify()
            self.queryLock.release()
            print("main is waiting a bit")
            time.sleep(1)


Loader()

Race conditions are fun :)


推荐阅读