2012-04-05 10 views
3

私は同じランダムシードで同じ結果が必要なアプリケーションを持っています。しかし、random.randintはスレッドセーフではありません。私はミューテックスを試しましたが、これはうまくいきません。ここに私の実験コードは(長い単純な)です:Pythonでランダムモジュールをスレッドセーフにする

import threading 
import random 

def child(n, a): 
    g_mutex = threading.Lock() 
    g_mutex.acquire() 
    random.seed(n) 
    for i in xrange(100): 
     a.append(random.randint(0, 1000)) 
    g_mutex.release() 

def main(): 
    a = [] 
    b = [] 
    c1 = threading.Thread(target = child, args = (10, a)) 
    c2 = threading.Thread(target = child, args = (20, b)) 
    c1.start() 
    c2.start() 
    c1.join() 
    c2.join() 

    c = [] 
    d = [] 
    c1 = threading.Thread(target = child, args = (10, c)) 
    c2 = threading.Thread(target = child, args = (20, d)) 
    c1.start() 
    c1.join() 
    c2.start() 
    c2.join() 

    print a == c, b == d 

if __name__ == "__main__": 
    main() 

私は、真真を印刷するためのコードにしたいが、それは偽、偽を与えるためにチャンスを立っています。スレッドセーフなランデントを作成するにはどうすればよいですか?

答えて

3

その他はスレッドセーフな方法でrandomを使用するための適切な方法を指摘しています。しかし、あなたが書いたコードはスレッドセーフではないことを指摘することが重要であると感じています。

def child(n, a): 
    g_mutex = threading.Lock() 
    g_mutex.acquire() 
    random.seed(n) 
    for i in xrange(100): 
     a.append(random.randint(0, 1000)) 
    g_mutex.release() 

各スレッドは、この方法を個別に実行しています。これは、各スレッドが独自のロックインスタンスを作成し、取得し、作業してから解放することを意味します。すべてのスレッドが同じロックを取得しようとしていない限り、非並列実行を保証するものはありません。 runメソッドのコンテキスト外でg_mutexに1つの値を割り当てる必要があります。

編集

私はただ単にグローバルロックへの切り替えは、あなたが言ったことを正確に何が保証​​されていないことを追加したいです。ロックにより、一度に1つのスレッドのみが数値を生成しますが、どのスレッドが最初に開始するかは保証されません。

+0

私はそれに気付かなかったとは思わない。あなたがグローバルロックを保持している場合は、スレッドに多くのポイントがあるわけではありません。 –

13

あなたはthe documentation for randomからスレッドごと

>>> import random 
>>> local_random = random.Random() 
>>> local_random.seed(1234) 
>>> local_random.randint(1,1000) 
967 
6

random.Randomの別のインスタンスを作成することができます

このモジュールによって提供される機能は、実際にはrandom.Randomの隠されたインスタンスのメソッドにバインドされていクラス。独自のインスタンスをインスタンス化して、状態を共有しないジェネレータを取得することができます。 マルチスレッドプログラムでは、各スレッドのランダムのインスタンスを作成し、jumpahead()メソッドを使用して、各スレッドが認識する生成されたシーケンスが重複しないようにすることができます。

ドキュメントには、このクラスが何であるかを正確に言うことはありませんが、それはclass random.SystemRandom([seed])を示していて、random.Random([seed])は同じのようです。

例:

local_random = random.Random(n) 
for i in xrange(100): 
    a.append(local_random.randint(0, 1000)) 
関連する問題