7

同じランダムシードが与えられた場合、同じ結果を必要とするアプリケーションがあります。しかし、random.randint はスレッドセーフではありません。ミューテックスを試しましたが、うまくいきません。これが私の実験コードです(長くても簡単です):

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

true, trueを出力するようにコーディングしたいのですが、 false, falseを与える可能性があります。スレッドセーフな randint を作成するにはどうすればよいですか?

4

3 に答える 3

24

random.Randomスレッドごとに個別のインスタンスを作成できます

>>> import random
>>> local_random = random.Random()
>>> local_random.seed(1234)
>>> local_random.randint(1,1000)
967
于 2012-04-05T02:30:28.127 に答える
11

のドキュメントrandomから:

このモジュールによって提供される関数は、実際には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))
于 2012-04-05T02:30:55.010 に答える
5

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

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

編集

グローバルロックに切り替えるだけでは、あなたが言ったことを正確に実行できるとは限りません. ロックは、一度に 1 つのスレッドだけが数値を生成することを保証しますが、どのスレッドが最初に開始されるかは保証しません。

于 2012-04-05T02:35:55.630 に答える