Допустимо ли разделять один экземпляр Random
класса между несколькими потоками? И, nextInt(int)
в частности, для вызова из нескольких потоков?
java
multithreading
random
thread-safety
Щеклеин
источник
источник
java.util.concurrent.ThreadLocalRandom
.Ответы:
Он потокобезопасен в том смысле, что он все равно будет генерировать случайные числа при использовании несколькими потоками.
Реализация Sun / Oracle JVM использует synchronized и AtomicLong в качестве начального числа для улучшения согласованности между потоками. Но, похоже, это не гарантируется для всех платформ в документации.
Я бы не стал писать вашу программу, требующую такой гарантии, тем более что вы не можете определить порядок, в котором
nextInt()
она будет вызвана.источник
Это потокобезопасный, хотя так было не всегда.
Видеть Http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 для получения дополнительной информации.
источник
Согласно документации, Math.random () гарантирует безопасность для использования несколькими потоками. Но класс Random - нет. Я предполагаю, что вам придется синхронизировать это самостоятельно.
источник
Да, Random является потокобезопасным.
nextInt()
метод вызывает защищенныйnext(int)
метод , который используетAtomicLong seed, nextseed
(атомный длинный) для создания следующего семени.AtomicLong
используется для обеспечения нитевой безопасности при генерации семян.источник
Как уже было сказано, это сохранение потока, но может быть разумно использовать в
java.util.concurrent.ThreadLocalRandom
соответствии с этой статьей (ссылка мертва). ThreadLocalRandom также является подклассом Random, поэтому он обратно совместим.источник
Нет причин, по которым несколько потоков не могут использовать одно и то же Random. Однако, поскольку класс не является явно потокобезопасным и поддерживает последовательность псевдослучайных чисел через начальное число. Несколько потоков могут иметь одно и то же случайное число. Было бы лучше создать несколько Random для каждого потока и по-разному их засеять.
РЕДАКТИРОВАТЬ : Я только что заметил, что реализация Sun использует AtomicLong, поэтому я предполагаю, что это потокобезопасный (как также отметил Питер Лоури (+1)).
EDIT2 : OpenJDK также использует AtomicLong для семени. Как уже говорили другие, полагаться на это по-прежнему нецелесообразно.
источник
Вот как я решил проблему, не предполагая, что Random использует атомарные переменные. Он все еще может случайным образом столкнуться, если
currentTime * thread id
в какое-то время будет одинаково, но это достаточно редко для моих нужд. Чтобы действительно избежать возможности коллизий, вы можете заставить каждый запрос ожидать уникальную временную метку часов.источник
(24*60*60*1000)
часть значима?(24*60*60*1000)
том, что поток с идентификатором12
вxxxxxxxxxx045
миллисекундах не засевается так же, как поток22
вxxxxxxxxxx035
миллисекундах. Однако у меня нет веских оснований предполагать, что идентификаторы потоков являются инкрементными, и нет веских причин думать, что завтра я создаю потоки в более случайное время, чем сегодня. Я упростил алгоритм и обновил описание, чтобы выявить недостаток.Random
Класс не настроен для одного экземпляра , которые будут использоваться в нескольких потоках. Конечно, если вы это сделаете, вероятно, вы увеличите вероятность непредсказуемости и приближения к случайным числам. Но поскольку это псевдослучайный генератор, я не понимаю, зачем вам нужно делиться экземпляром. Есть ли более конкретные требования?источник