2016-04-22 12 views
-2

由於不可預測的多重對稱線程的賽車情況,使用這種不確定性來建立統一的隨機發生器是否好?使用多線程比賽作爲一個隨機數發生器是一個好主意嗎?

例如,從http://www.cplusplus.com/reference/mutex/call_once/的代碼,調用它兩次以在[0,99]中生成一個隨機整數。

#include <iostream>  // std::cout 
#include <thread>   // std::thread, std::this_thread::sleep_for 
#include <chrono>   // std::chrono::milliseconds 
#include <mutex>   // std::call_once, std::once_flag 
int winner; 
void set_winner (int x) { winner = x; } 
std::once_flag winner_flag; 
void wait_1000ms (int id) { 
// count to 1000, waiting 1ms between increments: 
    for (int i=0; i<1000; ++i) 
    std::this_thread::sleep_for(std::chrono::milliseconds(1)); 
// claim to be the winner (only the first such call is executed): 
    std::call_once (winner_flag,set_winner,id); 
} 
int main() { 
    std::thread threads[10]; 
// spawn 10 threads: 
    for (int i=0; i<10; ++i) 
    threads[i] = std::thread(wait_1000ms,i+1); 
    std::cout << "waiting for the first among 10 threads to count 1000 ms...\n"; 
    for (auto& th : threads) th.join(); 
    std::cout << "winner thread: " << winner << '\n'; 
    return 0; 
} 

然後調用代碼(從http://advancedlinuxprogramming.com/alp-folder/alp-ch04-threads.pdf)某些時間的請求長度爲隨機位。

#include <pthread.h> 
#include <stdio.h> 
/* Prints x’s to stderr. The parameter is unused. Does not return. */ 
void* print_xs (void* unused) { 
    while (1) { 
    sleep(1); 
    fputc ('x', stderr); 
    } 
    return NULL; 
} 
int main() { 
    pthread_t thread_id; 
/* Create a new thread. The new thread will run the print_xs function. */ 
    pthread_create (&thread_id, NULL, &print_xs, NULL); 
/* Print o’s continuously to stderr. */ 
    while (1) { 
    sleep(1); 
    fputc ('o', stderr); 
    } 
    return 0; 
} 

那是真正統一無期?該序列無法重現,這可能是調試的弱點。

回答

1

使用線程時序作爲隨機源的問題(除了效率命中之外)是您沒有任何依據來相信您將返回的值將具有任何良好的分佈。線程調度器通常會盡量公平,這意味着他們會嘗試給每個線程提供大致相等的時間,並通過估計每個線程需要多少時間來調整。這樣做的方式完全取決於調度程序是如何實現的,並且由於調度程序沒有對隨機性進行優化,因此您返回的任何隨機應該被視爲「有點但不是很隨機」。如果這確實是一致隨機的,那純粹是巧合,幾乎肯定不會是便攜式的。更糟糕的是,它不會是一致隨機的,所以你沒有理由相信你正在做的工作,因此沒有人會有理由相信你在做什麼。

我不確定這是否是純粹的假設性問題。如果你真的想要這樣做,你應該停下來問問爲什麼你想這樣做。如果您只需要一個「足夠好」的隨機源,請使用庫默認值。如果您需要密碼保護的某些內容,請使用/dev/random來獲得最佳的隨機字節,如果沒有足夠的字節,則以最佳實踐證明的方式將其提供給密碼安全的哈希函數。現在,很多操作系統確實使用線程定時信息作爲熵累加器的輸入,然後用它們來獲取高質量的隨機比特。因爲這些值與其他看似不可預知的事件(網絡數據,電容放電,屏幕內容,CPU溫度,時鐘時間等)混合在一起,將每個熵組合成單個高熵源的方式,這是有效的。如果你想使用這樣的信息來獲得隨機性,只需閱讀/dev/random或使用另一種操作系統特定的機制來獲取高熵字節即可。

相關問題