使用python线程锁和circulair导入时出现意外行为

use*_*293 5 python multithreading locking

我用线程锁编写了一个简单的测试程序.此程序的行为不符合预期,python解释器不会抱怨.

test1.py:

from __future__ import with_statement
from threading import Thread, RLock
import time
import test2

lock = RLock()

class Test1(object):
    def __init__(self):
        print("Start Test1")
        self.test2 = test2.Test2()
        self.__Thread = Thread(target=self.myThread, name="thread")
        self.__Thread.daemon = True
        self.__Thread.start()
        self.test1Method()

    def test1Method(self):
        print("start test1Method")
        with lock:
            print("entered test1Method")
            time.sleep(5)
            print("end test1Method")

    def myThread(self):
        self.test2.test2Method()

if __name__ == "__main__":
    client = Test1()
    raw_input()
Run Code Online (Sandbox Code Playgroud)

test2.py:

from __future__ import with_statement
import time
import test1

lock = test1.lock

class Test2(object):
    def __init__(self):
        print("Start Test2")

    def test2Method(self):
        print("start test2Method")
        with lock:
            print("entered test2Method")
            time.sleep(5)
            print("end test2Method")
Run Code Online (Sandbox Code Playgroud)

两个睡眠都在同一时间执行!不是我在使用锁时的预期.

当test2Method移动到test1.py时一切正常.当我在test2.py中创建锁并将其导入test1.py时,一切正常.当我在一个单独的源文件中创建锁并在test1.py和test2.py中导入它时一切正常.

可能它与circulair进口有关.

但为什么python不抱怨这个?

Lau*_*low 1

print在语句之前和之后使用语句并在创建后立即import打印表明实际上正在创建两个锁。看来该模块被导入了两次,mouad在他的回答中解释说,这是因为先导入为,然后导入为,这导致锁被实例化两次。id(lock)test1.py__main__test1

尽管如此,使用全局锁无论如何都不是一个好的解决方案。有几种更好的解决方案,我想您会发现其中一种能够满足您的需求。

  • 将锁实例化为 的类变量Test1,并将其作为参数传递给Test2

  • 将锁实例化为Test1in的普通变量__init__,并将其作为参数传递给Test2

  • 实例化块中的锁if __name__ == "__main__"并将其传递给Test1,然后传递给Test1to Test2

  • 在块中实例化锁if __name__ == "__main__",首先实例化Test2锁,然后将Test2实例锁传递给Test1。(这是最解耦的方法,我建议使用这种方法。它至少会简化单元测试。)。

这是最后一个建议的代码:

test1.py:

class Test1(object):
    def __init__(self, lock, test2):
        print("Start Test1")
        self.lock = lock
        self.test2 = test2
        self.__Thread = Thread(target=self.myThread, name="thread")
        self.__Thread.daemon = True
        self.__Thread.start()
        self.test1Method()

    def test1Method(self):
        print("start test1Method")
        with self.lock:
            print("entered test1Method")
            time.sleep(1)
            print("end test1Method")

    def myThread(self):
        self.test2.test2Method()

if __name__ == "__main__":
    lock = RLock()
    test2 = test2.Test2(lock)
    client = Test1(lock, test2)
Run Code Online (Sandbox Code Playgroud)

test2.py:

class Test2(object):
    def __init__(self, lock):
        self.lock = lock
        print("Start Test2")

    def test2Method(self):
        print("start test2Method")
        with self.lock:
            print("entered test2Method")
            time.sleep(1)
            print("end test2Method")
Run Code Online (Sandbox Code Playgroud)