简体   繁体   English

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

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

So, I need some help with multithredding in C++. 所以,我需要一些C ++中多线程的帮助。 I would like to have my multiple threads call the function usleep with a random number below 800. However, from my understanding, rand_r must be seeded with a different integer in each thread. 我想让我的多个线程用800以下的随机数调用函数usleep。但是,根据我的理解,rand_r必须在每个线程中以不同的整数播种。

My confusion stems from the fact that if I want a different integer to be used for rand_r for each thread, then how can I do this? 我的困惑源于这样一个事实,即如果我想为每个线程使用不同的整数rand_r,那么我该怎么做呢? How can I have a different (ie. random) integer be used for each thread, if I can't create random integers? 如果我不能创建随机整数,我怎样才能为每个线程使用不同的(即随机)整数?

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
    }
}

I have the static integers producerseed and consumerseed defined at the top of the program, as global variables . 我将在程序顶部定义的静态整数producerseed和consumerseed作为全局变量 I did it this way because I thought that the calls to rand_r needed to access a static, non-changing memory location. 我是这样做的,因为我认为对rand_r的调用需要访问一个静态的,不变的内存位置。

Is this the correct way to do this? 这是正确的方法吗? Or do I need different integers for each thread. 或者我是否需要为每个线程使用不同的整数。 Will this result in any race conditions in my threads? 这会导致我的线程中出现任何竞争条件吗? What about the random number generated -- will it be different every time? 生成的随机数怎么样 - 每次都会有所不同?

Edit 1: Okay, so the answer to that question was basically that it is incorrect . 编辑1:好的,所以这个问题的答案基本上是不正确的 You need a unique seed integer for each thread. 每个线程都需要一个唯一的种子整数。 This can come from, for example, time() or the p_thread_self() id. 这可以来自,例如,time()或p_thread_self()id。 I'm still confused as to how to implement this exactly, but I will work on it and report back. 我仍然对如何准确实现这一点感到困惑,但我将继续努力并报告。 Right now I decided to use p_thread_self as the seed for each thread. 现在我决定使用p_thread_self作为每个线程的种子。

Thank you so much for taking the time to look/answer. 非常感谢您花时间寻找/回答。

In C++11, you could simply create another independent seed on each thread using std::random_device . 在C ++ 11中,您可以使用std::random_device在每个线程上创建另一个独立种子。 This is exactly the same as you would do in single-threaded code. 这与您在单线程代码中完全相同。 You can then call thread::sleep() on std::this_thread . 然后,您可以在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);

In particular, there is no need to (ab)use the current time as seed and/or other correlated seeds. 特别地,不需要(ab)使用当前时间作为种子和/或其他相关种子。

  1. You need 1 seed per thread, not a global seed. 每个线程需要1个种子,而不是全局种子。
  2. To generate a unique seed per thread, call time() from the main thread to get the first seed. 要为每个线程生成唯一种子,请从主线程调用time()以获取第一个种子。 Then for each new thread, add one to the current seed to get the next seed. 然后,对于每个新线程,将一个添加到当前种子以获取下一个种子。 For example, if time() returned 100, your seeds would be 100, 101, 102, etc. Your main thread would need to pass the seed to each thread as part of the arguments to the thread. 例如,如果time()返回100,那么你的种子将是100,101,102等。你的主线程需要将种子传递给每个线程作为线程参数的一部分。

Edit: 编辑:

  1. As the comments below showed, you can take the initial seed ( 100 in the example above) and mix it with the thread id (using xor or addition). 如下面的注释所示,您可以获取初始种子(上面示例中的100 )并将其与线程ID(使用xor或add)混合。 That way you don't have to pass the seed to each thread. 这样您就不必将种子传递给每个线程。 As far as only using the thread id as a seed, that would work also. 至于使用线程id作为种子,那也可以。 However, on a new run, you might get the same thread ids as a previous run (depending on how your OS determines thread ids). 但是,在新的运行中,您可能会获得与先前运行相同的线程ID(取决于您的操作系统如何确定线程ID)。 So if you don't want to depend on how your OS generates thread ids, you should still use some initial seed such as the time. 因此,如果您不想依赖于操作系统如何生成线程ID,您仍应使用一些初始种子,例如时间。

My confusion stems from the fact that if I want a different integer to be used for rand_r for each thread, then how can I do this? 我的困惑源于这样一个事实,即如果我想为每个线程使用不同的整数rand_r,那么我该怎么做呢? How can I have a different (ie. random) integer be used for each thread, if I can't create random integers? 如果我不能创建随机整数,我怎样才能为每个线程使用不同的(即随机)整数?

Here you need to use thread specific variable. 在这里,您需要使用特定于线程的变量。 So you can use these method. 所以你可以使用这些方法。

pthread_setspecific() & pthread_getspecific()

This is used to create variables that are global, but still specific to each thread (not shared): They are thread-specific global variables. 这用于创建全局变量,但仍然特定于每个线程(不共享):它们是特定于线程的全局变量。

This examples has good example of https://stackoverflow.com/a/15101240/775964 这个例子有https://stackoverflow.com/a/15101240/775964的好例子

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

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