这是一道阿里的笔试题。
在linux下使用pthread_create和sleep函数实现,利用线程的随机调度特性和sleep函数的低精度特性,在主程序中创建了和字符数相同数量的线程,将线程的编号传给每个线程的处理函数,这个编号也对应字符串的下标,在线程处理函数中,首先调用sleep函数,然后将该下标处的字符和下标为0处的字符交换。
在上面的过程中,有两个步骤引入了随机性,一个是线程的随机调度特性导致线程处理函数的调用顺序随机,另一个是调用了低精度的sleep函数,后进入睡眠的线程可能会比先进入睡眠的线程还要先苏醒,这两种随机性导致交换操作执行的不确定,从而产生比较理想的伪随机序列。
实际测试中,第一种线程调度的随机性并不是很强,在注释掉sleep函数后单测利用线程随机调度特性产生伪随机序列:
可见序列的随机性并不是很强,在增加sleep函数后,带来了更强的随机性,如下图所示,伪随机序列的随机性要比上面的好很多。
linux下的C代码:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
char str[]="abcdefghij";
pthread_mutex_t mutex;
void thread_fun(void* param)
{
char temp;
sleep(2);
pthread_mutex_lock(&mutex);
temp=str[0];
str[0]=str[(int)param];
str[(int)param]=temp;
pthread_mutex_unlock(&mutex);
}
int main()
{
pthread_t tid[10];
int ret;
int i;
pthread_mutex_init(&mutex,NULL);
for(i=0;i<10;i++)
{
ret=pthread_create(&tid[i],NULL,thread_fun,(void*)i);
if(ret!=0)
{
printf("create thread error!");
return 1;
}
}
for(i=0;i<10;i++)
pthread_join(tid[i],NULL);
printf("%s\n",str);
return 0;
}计算机本身是一个可预测的系统,采用这种软件的方法并不能产生真正的随机数,尽管伪随机数带有一定的随机特征,但这些数字序列并非统计意义上的随机数。为了取得真正的随机数,linux内核采用了一种很高明的方法,使用外部中断来产生随机数,比如我们在使用计算机时敲击键盘的时间间隔,移动鼠标的距离与间隔,特定中断的时间间隔等等,这些相对于计算机来说,都是不可预测和非确定的,通过记录这些外部中断的信息,可以有效的给应用程序提供真正的随机数,不过这些已经不属于我们今天讨论的范围了。
本文介绍了一种在Linux环境下利用pthread_create和sleep函数结合线程的随机调度及sleep函数的低精度特性来生成伪随机序列的方法。通过创建与字符串长度相同数量的线程,并在每个线程中进行字符交换,利用线程调度和sleep函数的不确定性增强了随机性。

被折叠的 条评论
为什么被折叠?



