2012-10-24 35 views
0

有人可以告诉我,如果以下线程安全与否,以及如果它不是我必须做什么才能使它如此。蟒蛇线程上的线程安全锁

注意:这只是一个小样本,不知道它是否运行。

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

这取决于你正在使用的实现和你在做什么。

首先,在事实上标准实现的Python(“CPython的”)中,仅允许一个线程,因为Python解释器不是线程安全的一些内部同时运行。这由全球解释器锁(又名“GIL”)控制。所以在cpython中,你根本不需要额外的锁; GIL确保一次只有一个线程正在运行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

如果我正确理解你,你想告诉你的线程何时停止。由于这是一个只有一个线程写入共享变量并且只写一次的情况,所以您不需要锁定。

当您正在并发修改无法自动读取的共享数据结构时,锁定是必需的。

+0

什么时候一个人可以写作,一个人可以同时阅读?或者这会不会发生? –

+1

@aspect它并不重要 - 因为你只是改变一个布尔False为真,没有“临时”写入状态,其他线程可以ee – katrielalex