2015-04-06 107 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)使用當前時間作爲種子和/或其他相關種子。

    相關問題