有人可以告诉我以下是否有线程安全,如果不是我必须做的事情。
注意:这只是一个小样本,不确定它是否会运行。
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()
答案 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)
如果我理解正确,您希望在线程发出停止信号。由于这种情况只有一个线程写入共享变量而且只有一次,因此您不需要锁定。
当您同时修改无法原子读取的共享数据结构时,锁是必需的。