【问题标题】:Make the random module thread-safe in Python在 Python 中使随机模块线程安全
【发布时间】:2012-04-05 02:26:44
【问题描述】:

我有一个应用程序需要在给定相同随机种子的情况下获得相同的结果。但我发现 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?

【问题讨论】:

    标签: python random thread-safety


    【解决方案1】:

    您可以为每个线程创建单独的 random.Random 实例

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

    【讨论】:

      【解决方案2】:

      来自the documentation for 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))
      

      【讨论】:

        【解决方案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 分配一个值。

        编辑

        我只想补充一点,简单地切换到全局锁并不能保证完全按照您所说的进行。锁将确保一次只有一个线程在生成数字,但不保证哪个线程将首先启动。

        【讨论】:

        • 不敢相信我没有注意到这一点。如果您持有全局锁,那么线程并没有多大意义。
        猜你喜欢
        • 2019-08-09
        • 2011-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-31
        • 2012-07-13
        • 1970-01-01
        相关资源
        最近更新 更多