在C语言的多线程程序中生成随机数

5

我正在编写一个程序,其中有工作线程创建从0到3或从0到x-1(一个变量)的随机数。

我需要学习的是如何在C中生成这些随机数。

我正在使用gcc编译器,并在Ubuntu 11.10上工作。


2
“从0到3,从0到x-1”是什么意思?你的意思是需要x个随机值位于0到3之间吗? - Shraddha
1
你是在问关于随机部分还是多线程部分或者两者都要学习的内容? - Tudor
x是一个整型变量的名称。 - Salih Erikci
1
如果您使用的是POSIX系统,请尝试使用其中一个drand48函数(可能是nrand48())。 - pmg
@littlestewie:请提供您的环境(平台、编译器)的详细信息,因为答案会根据这些信息而有所不同。 - Alok Save
5个回答

9

rand()srand()在这种情况下都不能安全地使用。

它们既不可重入也不线程安全。一般来说,C语言和C++标准对于任何标准库函数的线程安全性都没有任何要求。
某些实现确实可以提供线程安全版本,但这并不是标准要求。

为了能够在多线程环境中使用随机数生成器,您需要使用一个允许传递状态的实现。这样,您可以为每个线程保留一个状态值,生成高质量的随机数而无需进行同步。

C标准库没有提供任何选择。这使得100%的可移植性变得相当困难。您应该在问题中提到您的环境,以获得准确的答案。

请查看GNU Scientific Library,它声称提供多线程随机数生成器


我以前在Linux和Windows上使用GSL时没有遇到任何问题 - 请注意,每个线程都需要自己的随机数生成器(使用gsl_rng_alloc创建)。也就是说,通过拥有多个随机数生成器,每个生成器都有自己的状态,而不是在每次使用生成器时锁定状态来实现线程安全。 - James
通常情况下,当一个函数不是线程安全的时候,你可能会得到意外的结果。但如果 rand 返回意外的结果,那么问题在哪里? - ugoren
@ugoren:你可能会从一个本应该给你随机值的函数中得到完全相同的值,这不是一个问题吗? - Alok Save
@Als,一个正确的 rand() 实现也会有一定概率给出完全相同的随机值。但原则上来说你是对的,因为使用正确的 rand() 时这是已知的概率,而在这种情况下不是这样。如果用于密码学,这实际上可能很重要。 - ugoren
在模拟研究中,通常希望能够复制“随机”模拟数据的结果。这就是为什么随机数生成器通常允许您自行设置种子的原因。因此,它可能很重要。 - Placidia

1

使用rand_r()(参见 rand(3))

函数rand_r()需要一个指向无符号整型的指针作为状态参数。

它是可重入的,并且以种子作为输入,因此线程可以独立地管理其种子。


1
如果您只需要一些随机数,并且不在乎这些随机数的序列是否独立生成
    #include <stdlib.h>                       
    #include <stdio.h>                        
    #include <pthread.h>                      
    #include <unistd.h>                       

    void* cb1(void*) {                        
        while(1) {                            
            printf("cb1, rand:%d\n",rand());  
            sleep(1);                         
        }                                     
    }                                         

    void* cb2(void*) {                        
        while(1) {                            
            printf("cb2, rand:%d\n",rand());  
            sleep(1);                         
        }                                     
    }                                         


    int main() {                              
        pthread_t  th1, th2;                  
        srand(1);                             
        pthread_create(&th1, NULL, cb1, NULL);
        pthread_create(&th2, NULL, cb2, NULL);

        pthread_join(th1, NULL);              
        pthread_join(th2, NULL);              

        return 0;                             
    }                                         

0

真实而美丽的事物;

http://en.wikipedia.org/wiki/Mersenne_twister

编写自己的随机数生成器。

(抱歉。我刚刚看了一下那个维基页面。我上次看的时候还好,你可以阅读它并实现扭曲器。现在它是一堆学位级别的数学,对任何人都没有解释,除了那些花了四年时间在大学学习数学的人群。我在维基上经常看到这种情况 :-(


也许不会太久 - 我的印象是在讨论中有人争辩伪代码不是真正的伪代码。预计该页面在不久的将来将完全无用 :-/ - user82238
2
不要为生产使用编写自己的代码。千万不要这样做。已经存在经过良好调试的实现。 - dmckee --- ex-moderator kitten

0
一个简单的版本,缺少错误检查,使用C11的threads.h,看起来像这样:
mtx_t rand_mtx;

//run only once.
int rand_init(int seed)
{
     srand(seed);
     mtx_init(&rand_mtx, mtx_plain);
} 

int synced_rand()
{
    mtx_lock(&rand_mtx);
    int r = rand();
    mtx_unlock(&rand_mtx);
    return r;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接