С
Компілюйте прапор -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
EDIT:
Дав трохи більше думки і зрозумів, що цей час взагалі не заснований. Навіть при повністю детермінованому планувальнику ентропія не походить від часових відрізків - це відбувається від завантаження всіх запущених процесів у системі.
EDIT 2
Після отримання деякого натхнення від @Quincunx розміщення кривої дзвінка, я скинув 12 МБ випадковості у файл і завантажив його в CAcert . Він не вдався до всіх твердих тестів, але отримав поважних 7,999573 з 8 на тесті ЛОР (лише Потенційно детермінований). Цікаво, що подвоєння кількості ниток погіршило її.