2016-10-18 1 views
2

以下のコードはスレッドセーフですか?
1つ目のスレッドのみが変数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

私の心配であるマシン工学 – ealeon

答えて

3

絶対にありません。

それは2つのスレッドが次のいずれかを実行する前に、この行を実行することは十分に可能である。その後

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() 

1つのスレッドだけが可能ですを取得します。ロックを取得します。別のスレッドがロックされている間に別のスレッドがロックを取得しようとすると、lock.acquire()の呼び出しはブロックされ、ロックがに解放されて最初のスレッドによってに解放されるまで待機します。次に、他のスレッドによってロックが取得されます。

このようにして、コードはlock.acquire()lock.release()の間で一度に1つのスレッドで確実に実行されます。

EDIT

ゲルハルトはthe other answerで指摘したように、あなたがロックしてcontext management protocolを使用することができますに:

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

もロックが正しくロックされた範囲内の例外の場合には解放されていることを確認しますブロック。

1

いいえ、そうではありません。現在のスレッドが 変数をフェッチした後に別のスレッドが制御を取得した場合、それは、変数を取得し、それをインクリメントし、現在のスレッドが同じことをする前に、それを バックを書くことができ

。そして、彼らは の両方が同じ元の値を見ているので、1つのアイテムだけが計算されます 。

Here'sこの良い記事については、

P.S.

global set_this_var_only_once 
4

あなたはこのような変数をロックする必要があります:また、次の行は、労働者()で必要とされる2人の以上の労働者が条件をチェックすると

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(lock){/ * code * /}と実質的に同じです。 –

関連する問題