2016-10-18 35 views
2

以下代码是否线程安全?
只有一个/第一个线程设置变量,set_this_var_only_once?Python:多线程设置变量一次

set_this_var_only_once = None 

def worker(): 
    global set_this_var_only_once 
    if set_this_var_only_once is None: 
     set_this_var_only_once = "not None" 

for i in range(10): 
    t = threading.Thread(target=worker) 
    t.daemon=True 
    t.start() 
+2

如果两个或更多的工人检查条件之前任何一方的设置变量? –

+0

@machineyearning这是我的担心 – ealeon

回答

3

绝对不是。

这很可能是两个线程执行下一个前执行这一行:

if set_this_var_only_once is None: 

之后,两个线程将执行下一行:

 set_this_var_only_once = "not None" 

您可以使用locks来防止:

lock = threading.Lock() 

def worker(): 
    lock.acquire() 
    if set_this_var_only_once is None: 
     set_this_var_only_once = "not None" 
    lock.release() 

只有一个线程将能够到获得的锁定。如果另一个线程在锁定时尝试获取它,对lock.acquire()的调用将会阻塞并等待,直到锁定为由第一个线程释放。然后该锁将由另一个线程获取。

这样可以确保lock.acquire()lock.release()之间的代码一次在一个线程中执行。

编辑

如格哈德在the other answer指出,可以用锁使用context management protocol

with lock: 
    if set_this_var_only_once is None: 
     set_this_var_only_once = "not None" 

这也将确保锁在一个异常的情况下,正确地释放内锁定块。

1

不,它不是。

如果另一个线程获取当前线程控制后已取出 的变量,它可以获取变量,增加它,并把它写回 ,当前线程做同样的事情之前。并且由于它们是 都看到相同的原始值,因此只有一个项目将被计入 。

Here's这篇关于它的好文章。

P.S.还需要在工人()以下行:

global set_this_var_only_once 
4

你需要锁定这样的变量:

from threading import Lock 

lock = Lock() 
set_this_var_only_once = None 

def worker(): 
    with lock: 
     if set_this_var_only_once is None: 
      set_this_var_only_once = "not None 
+1

使用'with'是一个很好的触摸;) – zvone

+0

使代码更清晰,并且与Java的同步块几乎相同,即synchronized(锁定){/ * code * /}。 –