簡體   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