繁体   English   中英

在C / C ++中使用rand_r进行多线程程序的正确方法

[英]Correct way to use rand_r for multithreaded programs in C/C++

所以,我需要一些C ++中多线程的帮助。 我想让我的多个线程用800以下的随机数调用函数usleep。但是,根据我的理解,rand_r必须在每个线程中以不同的整数播种。

我的困惑源于这样一个事实,即如果我想为每个线程使用不同的整数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作为每个线程的种子。

非常感谢您花时间寻找/回答。

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

#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)使用当前时间作为种子和/或其他相关种子。

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

编辑:

  1. 如下面的注释所示,您可以获取初始种子(上面示例中的100 )并将其与线程ID(使用xor或add)混合。 这样您就不必将种子传递给每个线程。 至于使用线程id作为种子,那也可以。 但是,在新的运行中,您可能会获得与先前运行相同的线程ID(取决于您的操作系统如何确定线程ID)。 因此,如果您不想依赖于操作系统如何生成线程ID,您仍应使用一些初始种子,例如时间。

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

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

pthread_setspecific() & pthread_getspecific()

这用于创建全局变量,但仍然特定于每个线程(不共享):它们是特定于线程的全局变量。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM