通知/释放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()
            ...

解决方法

我相信您确实不需要使用条件。看来,简单的Lock就可以完成您的任务。您实际上并没有验证是否满足某些条件,也没有使用条件的特殊方法wait()


也就是说,对于您提供的代码,您的主线程似乎太“快速”,并在另一个线程获得机会之前重新获取了锁。 这是您的代码的稍作修改的版本,在该版本中,主线程稍稍等待了一下,给另一个线程一个机会,它成功获取了锁定并继续。

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()

种族条件很有趣:)