Czy można współużytkować jedną instancję Random
klasy między wieloma wątkami? A nextInt(int)
zwłaszcza dzwonić z wielu wątków?
java
multithreading
random
thread-safety
Shcheklein
źródło
źródło
java.util.concurrent.ThreadLocalRandom
.Odpowiedzi:
Jest bezpieczny dla wątków w tym sensie, że nadal generuje liczby losowe, gdy jest używany przez wiele wątków.
Implementacja Sun / Oracle JVM używa synchronizacji i AtomicLong jako materiału siewnego, aby poprawić spójność między wątkami. Ale wydaje się, że nie jest to gwarantowane na wszystkich platformach w dokumentacji.
Nie napisałbym Twojego programu, aby wymagał takiej gwarancji, zwłaszcza że nie możesz określić kolejności w jakiej
nextInt()
będzie wywoływany.źródło
Jest bezpieczny dla wątków, chociaż nie zawsze.
Więcej informacji można znaleźć pod adresem http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 .
źródło
Zgodnie z dokumentacją Math.random () gwarantuje, że jest bezpieczny dla wielu wątków. Ale klasa Random nie. Zakładam, że będziesz musiał to sam zsynchronizować.
źródło
Tak, Random jest bezpieczny dla wątków.
nextInt()
sposób wymaga chronionegonext(int)
metody przy wykorzystaniuAtomicLong seed, nextseed
(atomowe długości), aby wygenerować następny nasion.AtomicLong
służy do zabezpieczenia nici podczas wytwarzania nasion.źródło
Jak powiedziano, jest to zapis wątków, ale rozsądne może być użycie
java.util.concurrent.ThreadLocalRandom
zgodnie z tym artykułem (link martwy). ThreadLocalRandom jest również podklasą Random, więc jest kompatybilny wstecz.źródło
Nie ma powodu, dla którego wiele wątków nie może używać tego samego Random. Jednakże, ponieważ klasa nie jest jawnie bezpieczna dla wątków i utrzymuje sekwencję liczb pseudolosowych za pośrednictwem ziarna. Wiele wątków może mieć tę samą liczbę losową. Byłoby lepiej, gdybyśmy utworzyli wiele Randomów dla każdego wątku i użyli ich inaczej.
EDYCJA : Właśnie zauważyłem, że implementacja Sun używa AtomicLong, więc myślę, że jest bezpieczna dla wątków (jak również zauważył Peter Lawrey (+1)).
EDIT2 : OpenJDK używa również AtomicLong jako materiału siewnego. Jak powiedzieli inni, nadal nie warto na tym polegać.
źródło
Oto, jak poradziłem sobie z problemem, nie zakładając, że Random używa zmiennych atomowych. W
currentTime * thread id
przyszłości może zderzyć się losowo, jeśli będzie równy, ale jest to wystarczająco rzadkie dla moich potrzeb. Aby naprawdę uniknąć kolizji, możesz kazać każdemu żądaniu czekać na unikalny znacznik czasu zegara.źródło
(24*60*60*1000)
część ma znaczenie?(24*60*60*1000)
Było tak, że wątek z ID12
wxxxxxxxxxx045
Millis nie wysiewa się tak samo jak nitka22
wxxxxxxxxxx035
Millis. Jednak nie mam żadnego dobrego powodu, by zakładać, że identyfikatory wątków są przyrostowe i nie ma powodu, by sądzić, że jutro tworzę wątki w bardziej losowych momentach niż dzisiaj. Uprościłem teraz algorytm i zaktualizowałem opis, aby zidentyfikować niedociągnięcie.Random
Klasa nie jest skonfigurowane do jednej instancji do wykorzystania w wielu wątkach. Oczywiście, jeśli to zrobiłeś, prawdopodobnie zwiększysz prawdopodobieństwo uzyskania nieprzewidywalnych i bliższych losowych liczb. Ale ponieważ jest to generator pseudolosowy, nie rozumiem, dlaczego miałbyś udostępniać instancję. Czy jest jakiś bardziej szczegółowy wymóg?źródło