С
Скомпилируйте с флагом -pthread (или с тем, что использует ваш компилятор).
#include <stdio.h>
#include <pthread.h>
#define m (unsigned long)2147483647
#define q (unsigned long)127773
#define a (unsigned int)16807
#define r (unsigned int)2836
static unsigned long seed;
pthread_t t[20];
int lo, hi, done;
void *pseudorandom(void *id)
{
while(done)
{
int test;
hi = seed/q;
lo = seed%q;
test = a * lo - r * hi;
if (test > 0) seed = test;
else seed = test + m;
}
}
main()
{
int i;
seed = 54321;
done = 1;
for(i = 0; i < 20; i++)
{
pthread_create(&(t[i]), NULL, &pseudorandom, NULL);
}
for (i = 0; i < 10; i++)
{
printf("%lu\n", seed);
}
done = 0;
}
Я не уверен, соответствует ли это стандарту «время не разрешено», потому что он в основном использует планировщик в качестве источника энтропии, преднамеренно игнорируя безопасность потоков. Он работает с использованием довольно простой псевдослучайной функции ( генератора случайных чисел Лемера ) с жестко закодированным начальным начальным числом . Затем он запускает 20 потоков, которые все выполняют вычисление Лемера с общим набором переменных.
Кажется, работает довольно хорошо, вот несколько последовательных прогонов:
comintern ~ $ ./a.out
821551271
198866223
670412515
4292256
561301260
1256197345
959764614
874838892
1375885882
1788849800
comintern ~ $ ./a.out
2067099631
953349057
1736873858
267798474
941322622
564797842
157852857
1263164394
399068484
2077423336
РЕДАКТИРОВАТЬ:
Дайте немного больше думать и понял, что это не на основе времени вообще. Даже с полностью детерминированным планировщиком энтропия не исходит из временных интервалов - она зависит от загрузки всех запущенных процессов в системе.
РЕДАКТИРОВАТЬ 2
После того, как @Quincunx опубликовал кривую колокольчика, я скопировал 12 МБ случайности в файл и загрузил его в CAcert . Он провалил все несгибаемые тесты, но набрал приличный 7.999573 из 8 в тесте ЛОР (только потенциально детерминированный). Любопытно, что удвоение количества потоков ухудшило ситуацию.