今天正好Debug到多线程产生随机数,发现传统的srand(time(NULL))已经不管用了(由于线程开始的时间可能相同,导致随机数种子一样),在网上查询了一番。给出的方法无非两种:
- 获取更精确的时间单位(time(NULL)获取的是秒为单位的时间),如毫秒ms,或者微秒us
- 使用线程ID作为随机数种子
经过测试发现:
- 随机数种子声明的位置会影响随机数的结果,这里的位置,主要是指线程内/外。具体见图一,图二
- 仅用线程ID仍然无法避免产生相同随机数的可能(原因我还没想明白,不知道各位大佬有懂的没),具体见图二
图一:使用线程ID在线程外声明随机数种子(高亮与最后一排)
图二:使用线程ID在线程内声明随机数种子(倒数第二、四排)
按照网上的说法,随机数种子肯定是应该声明在线程内的,这一点我是认同的,为了解决单纯使用ID仍然存在的随机数相同的问题,我决定采用微秒级别的时间+线程ID作为随机数种子(毫秒级别的时间经过测试仍然有可能相同),测试结果如图
附:随机数种子生成部分的代码
DWORD id = GetCurrentThreadId();
LARGE_INTEGER nFreq, t1;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&t1);
double dt = (double)t1.QuadPart / (double)nFreq.QuadPart * 1000000;
srand(id+dt);
以上,欢迎大佬指正。