python线程安全锁定循环

时间:2012-10-24 13:17:46

标签: python multithreading

有人可以告诉我以下是否有线程安全,如果不是我必须做的事情。

注意:这只是一个小样本,不确定它是否会运行。

TIMER = True
time_lock = threading.Lock()
def timing():
    while TIMER:
        # some logic will be here for now print time
        print time.time()

timer = threading.Thread(target=timing)
timer2 = threading.Thread(target=timing)
timer.start()
timer2.start()

while True:
    time_lock.aquire()
    if doSomeStuff():
        TIMER = True
    if otherThings():
        break
    time_lock.aquire()
    TIMER = False
    time_lock.release()

time_lock.aquire()
TIMER = False
time_lock.release()

2 个答案:

答案 0 :(得分:2)

这取决于您使用的实施方式以及您正在做的事情。

首先,在python(“cpython”)的事实上的标准实现中,由于python解释器的某些内部结构不是线程安全的,因此一次只允许运行一个线程。这由Global Interpreter Lock(又名“GIL”)控制。所以在cpython中,你根本不需要额外的锁; GIL确保一次只有一个线程运行python代码并可能更改变量。这是实现的一个特征,而不是语言。

其次,如果只有一个线程将写入一个简单变量而其他线程只读它,你也不需要锁定,原因显而易见。然而,作为程序员,你应该确保这种情况,并且很容易犯错误。

即使是一个简单的变量,也可能不需要锁定。在python中,变量更像是用于引用对象的标签,而不是可以放入内容的框。所以简单的赋值是原子的(在某种意义上它们不能被中途中断),正如你看到的那样你可以看到生成python字节码:

In [1]: import dis

In [2]: x = 7

In [3]: def setx():
    global x
    x = 12
   ...:     

In [4]: dis.dis(setx)
  3           0 LOAD_CONST               1 (12)
              3 STORE_GLOBAL             0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        

更改x的唯一代码是单个STORE_GLOBAL操作码。所以变量要么改变要么不改变;中间没有不一致的状态。

但如果你是想要测试特定值的变量,并在该测试仍然成立时执行操作,您需要锁定。因为另一个线程可能在您测试之后就已经更改了变量。

附加到列表或交换变量之类的东西不是原子的。但是再次在cpython中,这些将受到GIL的保护。在其他实现中,您需要锁定此类操作以防止可能的不一致。

答案 1 :(得分:1)

如果我理解正确,您希望在线程发出停止信号。由于这种情况只有一个线程写入共享变量而且只有一次,因此您不需要锁定。

当您同时修改无法原子读取的共享数据结构时,锁是必需的。