2016-10-27 16 views
0

スレッドを使用するときは、主に共有データの同期に関するいくつかのことをよく理解する必要があります。あなたは、ロック、rlocks、セマフォーなどを使用する必要があります。非常にシンプルな共有データでも書いていますか?Pythonのアトミックアクセス(スレッドに関連)

たとえば、グローバルリソースを共有する2つのスレッド、つまり単純なブール変数があります。

import threading 
import random 
import time 

active = True 

class T1(threading.Thread): 
    def run(self): 
     while active: 
      print("Hello")  # do some work 
      time.sleep(0.1) 

class T2(threading.Thread): 
    def run(self): 
     global active 
     while random.random() > 0.05: 
      time.sleep(1) 
     active = False 

t1, t2 = T1(), T2() 
t1.start() 
t2.start() 
t1.join() 
t2.join() 

動作しているようですが、pythonが動作することを保証していますか?はいの場合は、正確にどのような理由で動作しますか?

私には3つの答えがあります。

  1. ブール変数のアクセスは常にアトミック(別のスレッドで中断できない)なので機能します。この場合、Pythonはアトミック操作として何を保証しますか?整数、リスト、辞書のアトミックなアクセスですか?
  2. Pythonは毎回このコードが動作することを保証しません。解決策は、両方のスレッドでアクティブ変数にアクセスするためにロックを使用することです。
  3. これは、1つのスレッドだけが変数を書き込むために機能します。もう一方のスレッドはそれを読み込みます。

ここでは、別のコードである:今

import threading 
import random 
import time 

numbers = [3] 

class T1(threading.Thread): 
    def run(self): 
     while sum(numbers) % 3 == 0: 
      print("Hello")  # do some work 
      time.sleep(0.1) 

class T2(threading.Thread): 
    def run(self): 
     global active 
     while random.random() > 0.2: 
      numbers.extend([1, 2]) 
      time.sleep(1) 
     numbers.append(4) 

t1, t2 = T1(), T2() 
t1.start() 
t2.start() 
t1.join() 
t2.join() 

を単一と "複合"命令numbers.extendできた([1、2])T1スレッドによって中断さ?この場合、1が追加された直後で2が追加される直前に、T2はT2の前に意図せず停止する可能性があります。

答えて

0

短い答え:それは常に(少なくともCPythonとは)作品

それが原因GIL(グローバルインタプリタロック)の作品。 https://wiki.python.org/moin/GlobalInterpreterLock

これは、2つのスレッドが同時にPythonコードを実行することを保証しないため、読み取り/書き込みが同時に行われることはありません。

CPy以外の特定の実装に関する質問があれば、それはおそらく独自の質問に値するでしょう。

CPythonを使用しているプログラマが依存するような動作を維持しようとする他のPython実装(CPython以外)はありますが、各プロジェクトがどの程度どの程度そうしているかわかりません。

+0

2つのスレッドからの行は任意にインターリーブされるかもしれませんが、あなたのコードは本当にアトミックな一連のアクションに依存しません。あなたのコードは原子的に実行されている単一行にのみ依存していますが、CPythonでは常に信頼できるはずです – stevenjackson121

+0

「同時にコード」と「単一の変数に」とはどういう意味ですか? Pythonでは、*単一*命令は変数や複雑なオブジェクトに対して多くのことを行うことができます。 Pythonは単一の命令(2つのオブジェクト間のコピーやループや関数呼び出しなど)を他のスレッドで中断することはできませんか?どのスレッドが別のスレッドを中断できるかを私はどのように理解できますか? – pozzugno

+0

*スレッドが任意の2つの命令間で別のスレッドを中断できるとは思いますが、わかりません。式 'i = 2 + 3 * 10 + 17'は多くの別々の命令を持っていますが、完全な右側が評価され、最後に割り当てi = 49が発生します。 'i'の値が以前に' 10'だった場合、 'i'の値を繰り返しチェックしている別のスレッドは' i == 10'または 'i == 49'しか見ません。「2 + 3 * 10 + 17」の計算中に「i」は決してない – stevenjackson121

関連する問題