多线程C程序调用rand()无法生成随机数,求解决方案
多线程C程序中rand()生成重复随机数的解决方法
我编写了如下多线程C程序,期望每个线程生成随机等待时间,但程序无法生成随机数。我已在每个线程中调用
srand(time(NULL)+getpid())为rand()播种,却仍得到相同的数值输出。我了解这是因为硬件运行速度过快,时钟速度快于rand函数的播种速度导致的,希望获取让rand()生成更多不同值的可行方法。
原程序代码
#include<pthread.h> #include<stdio.h> #include<stdint.h> #include<stdlib.h> #include<time.h> #include<unistd.h> #define ERROR_CREATE 1 #define ERROR_JOIN 2 // create the function to be executed as a thread void *thread(void *ptr) { uintptr_t type = (uintptr_t) ptr; // thread number srand(time(NULL) + getpid()); int wait = rand() % 10; // randomizes numbers from 0 to 9 sleep(wait); // waits in time intervals of seconds printf("Thread - %ld waiting for %d seconds\n",type, wait); return ptr; // returns the thread number } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "Error with command line arguments"); } int num_threads = atoi(argv[1]); pthread_t threads[num_threads]; // array of thread types for (long i = 1; i <= num_threads; i++) { if (pthread_create(&threads[i], NULL, thread, (void *)i) != 0) { fprintf(stderr,"Error: could not create thread"); return ERROR_CREATE; } } // terminate each thread assigned for (int i = 1; i <= num_threads; i++) { if (pthread_join(threads[i], NULL) != 0) { fprintf(stderr, "Error: could not terminate thread"); return ERROR_JOIN; } } return 0; }
可行解决方法
1. 主线程统一播种,线程内用互斥锁保护rand()
rand()本身不是线程安全的,多线程同时调用会导致竞态,但如果在主线程启动前只播种一次,再用互斥锁控制rand()的访问,可以避免重复种子问题:
修改后的核心代码:
#include<pthread.h> // ... 其他头文件不变 pthread_mutex_t rand_mutex; // 全局互斥锁 void *thread(void *ptr) { uintptr_t type = (uintptr_t) ptr; int wait; pthread_mutex_lock(&rand_mutex); wait = rand() % 10; pthread_mutex_unlock(&rand_mutex); sleep(wait); printf("Thread - %ld waiting for %d seconds\n",type, wait); return ptr; } int main(int argc, char **argv) { // ... 参数检查逻辑不变 srand(time(NULL)); // 主线程提前播种 pthread_mutex_init(&rand_mutex, NULL); // 初始化互斥锁 int num_threads = atoi(argv[1]); pthread_t threads[num_threads]; // 修正数组索引越界问题:从0开始循环 for (long i = 0; i < num_threads; i++) { if (pthread_create(&threads[i], NULL, thread, (void *)(i+1)) != 0) { fprintf(stderr,"Error: could not create thread\n"); return ERROR_CREATE; } } for (int i = 0; i < num_threads; i++) { if (pthread_join(threads[i], NULL) != 0) { fprintf(stderr, "Error: could not terminate thread\n"); return ERROR_JOIN; } } pthread_mutex_destroy(&rand_mutex); return 0; }
2. 每个线程使用独立随机数状态(推荐)
使用POSIX标准的rand_r()函数,每个线程维护自己的种子,避免多线程共享状态的问题。给种子加入线程编号,确保即使同一时间创建线程,种子也不重复:
修改后的线程函数:
void *thread(void *ptr) { uintptr_t type = (uintptr_t) ptr; // 种子组合时间、进程ID、线程编号,保证唯一性 unsigned int seed = time(NULL) + getpid() + type; int wait = rand_r(&seed) % 10; sleep(wait); printf("Thread - %ld waiting for %d seconds\n",type, wait); return ptr; }
3. 使用现代线程安全随机数API
直接调用无需手动播种、天生线程安全的随机数函数,比如BSD/macOS下的arc4random_uniform(),或者Linux下的getrandom():
// 使用arc4random_uniform的例子,直接生成0-9的随机数 int wait = arc4random_uniform(10);
额外注意点
- 原程序中
threads[num_threads]数组从索引1开始赋值会导致越界,需修正为从0开始循环。 rand() % 10生成的是0到9的整数,并非0到10,若需要包含10,应改为rand() % 11。
内容的提问来源于stack exchange,提问作者user20074138
相关产品推荐
相关产品推荐

