2015-04-06 59 views
4

所以,我需要一些C++多线程帮助。我想让我的多个线程使用低于800的随机数调用usleep函数。但是,从我的理解中,rand_r必须在每个线程中使用不同的整数。在C/C++中使用rand_r进行多线程程序的正确方法

My confusion源于这样一个事实,如果我想为每个线程使用不同的整数用于rand_r,那么我该怎么做?如果我不能创建随机整数,如何为每个线程使用不同的(即随机)整数?

static unsigned int consumerseed = 1; 
static unsigned int producerseed = 54321; 

//producer thread: 
void *producer(void *param) { 
    buffer_item rand; 
    while (1) { 
     //sleep for a random period of time: 
     int producersleeptime = rand_r(&producerseed)%500+100; 
     usleep(producersleeptime); 
     //produce an item: 
     //wait on both semaphores 
     //attempt to insert into buffer 
     //signal both semaphores 
    } 
} 

//consumer thread: 
void *consumer(void *param) { 
    buffer_item rand; 
    while (1) { 
     //sleep for a random period of time: 
     int consumersleeptime = rand_r(&consumerseed)%600+200; 
     usleep(consumersleeptime); 
     //wait on both semaphores 
     //attempt to remove an item from buffer 
     //signal both semaphores 
    } 
} 

我有静态整数producerseed,并在程序的顶部consumerseed定义为全局变量。我这样做是因为我认为对rand_r的调用需要访问一个静态的,不变的内存位置。

这是正确的方法吗?或者我需要不同的整数为每个线程。这将导致我的线程中的任何竞争条件?生成的随机数怎么样 - 每次都会有所不同?

编辑1:好的,所以这个问题的答案基本上是不正确。每个线程需要一个独特的种子整数。这可以来自例如time()或p_thread_self()id。我仍然对如何正确实施这个问题感到困惑,但我会努力并报告。现在我决定使用p_thread_self作为每个线程的种子。

非常感谢您花时间查看/回答。

回答

1
  1. 你需要每个线程的一号种子,而不是一个全球性的种子很好的例子。
  2. 要为每个线程生成一个唯一的种子,请从主线程调用time()以获取第一个种子。然后为每个新线程添加一个到当前种子以获得下一个种子。例如,如果time()返回100,则您的种子将为100,101,102等。您的主线程需要将种子传递给每个线程,作为线程参数的一部分。

编辑:

  • 如下面的评论显示,可以采取(在上面的例子100)初始种子,并将其与线程id混合(使用异或或增加)。这样你就不必把种子传给每个线程。至于只有使用线程ID作为种子,这也将工作。但是,在新的运行中,您可能会获得与之前运行相同的线程ID(这取决于您的OS如何确定线程ID)。所以,如果你不想依赖你的操作系统如何生成线程ID,你仍然应该使用一些初始种子,比如时间。
  • +2

    #2的另一个选项是将thread-id(从“pthread_self”或等价物获得)混合到基于时间的种子中。这消除了中心线程创建者需要知道种子的需要。 – user4815162342 2015-04-06 11:25:32

    +0

    使用thread_id作为每个线程的种子怎么样?我想这会为每个线程创建一个独特的,大致随机的种子。我没有使用时间。这是我现在所做的,但我还没有测试过。 – Musicode 2015-04-06 18:02:36

    +1

    @ Musiccode看我的编辑。你说什么会奏效。它不如一时混合那么安全,因为你无法确定操作系统要分配给你的线程ID。 – JS1 2015-04-06 18:07:07

    0

    我的困惑源于这样一个事实,如果我想要一个不同的整数到 用于rand_r为每个线程,那么我该怎么做?我如何 有一个不同的(即随机)整数用于每个线程,如果我 不能创建随机整数?

    这里您需要使用线程特定的变量。所以你可以使用这些方法。

    pthread_setspecific() & pthread_getspecific() 
    

    这是用于创建是全局变量,但还是具体到每个线程(不共享):他们是特定于线程的全局变量。

    这个例子有https://stackoverflow.com/a/15101240/775964

    +1

    那么,因为它们是随机变量,我不能只是使用类似时间的东西吗?我仍然困惑。 – Musicode 2015-04-06 06:00:30

    +0

    @Musicode是的,你可以使用它但是为了这个目的,使用rand()是最复杂的方法。 – 2015-04-06 06:12:04

    +0

    'pthread_getspecific'和'pthread_setspecific'只能在提供POSIX线程API的系统上使用。 – user4815162342 2015-04-06 11:17:39

    4

    在C++ 11中,您可以简单地在每个线程上使用std::random_device创建另一个独立的种子。这与您在单线程代码中所做的完全相同。您可以致电thread::sleep()std::this_thread

    #include <random> 
    #include <thread> 
    #include <chrono> 
    
    thread_local std::random_device rd; // used once only per thread to initialise RNG 
    thread_local std::mt19937 rng(rd()); // thread-specific RNG 
    std::uniform_int_distribution<int> uni(0,800); // guaranteed unbiased 
    
    // called possibly many times 
    std::this_thread::sleep_for(uni(rng)*std::chrono::microseconds); 
    

    具体而言,不需要(ab)使用当前时间作为种子和/或其他相关种子。

    相关问题