Czy wątek klasy Random jest bezpieczny?


110

Czy można współużytkować jedną instancję Randomklasy między wieloma wątkami? A nextInt(int)zwłaszcza dzwonić z wielu wątków?


@Bala R, nie, nie mówimy o obiekcie Random w języku C #, ale o Javie.
Buhake Sindi

ups. przepraszam przegapiłem tę część.
Bala R

Dbanie o użycie Random w celu uzyskania liczb w środowisku wielowątkowym może dać złe wyniki. Może to nie ma znaczenia, ale jeśli wykonujesz jakieś symulacje, dobrze jest wiedzieć.
Maxence SCHMITT

14
Dla dalszych czytelników: istnieje nowa klasa o nazwie 1.7 java.util.concurrent.ThreadLocalRandom.
Jin Kwon

Odpowiedzi:


66

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.


69
W dokumentacji Java 7 dodano gwarancję: „Instancje java.util.Random są bezpieczne dla wątków”. docs.oracle.com/javase/7/docs/api/java/util/Random.html
Matt R,



7

Tak, Random jest bezpieczny dla wątków. nextInt()sposób wymaga chronionego next(int)metody przy wykorzystaniu AtomicLong seed, nextseed(atomowe długości), aby wygenerować następny nasion. AtomicLongsłuży do zabezpieczenia nici podczas wytwarzania nasion.


6

Jak powiedziano, jest to zapis wątków, ale rozsądne może być użycie java.util.concurrent.ThreadLocalRandomzgodnie z tym artykułem (link martwy). ThreadLocalRandom jest również podklasą Random, więc jest kompatybilny wstecz.

W artykule związane z nim porównała wyniki profilowania różnych klas Losowo: java.util.Random, java.util.concurrent.ThreadLocalRandom i java.lang.ThreadLocal<java.util.Random>. Wyniki pokazały, że użycie ThreadLocalRandom jest najbardziej wydajne, a następnie ThreadLocal i najgorzej działającego samego Random.


4

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ć.


3

Oto, jak poradziłem sobie z problemem, nie zakładając, że Random używa zmiennych atomowych. W currentTime * thread idprzyszł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.

/**
 * Thread-specific random number generators. Each is seeded with the thread
 * ID, so the sequence of pseudo-random numbers are unique between threads.
 */
private static ThreadLocal<Random> random = new ThreadLocal<Random>() {
    @Override
    protected Random initialValue() {
        return new Random(
            System.currentTimeMillis() *
            Thread.currentThread().getId());
    }
};

W górę! P: czy (24*60*60*1000)część ma znaczenie?
Jin Kwon

1
Tak, to była brudna sprawa. (24*60*60*1000)Było tak, że wątek z ID 12w xxxxxxxxxx045Millis nie wysiewa się tak samo jak nitka 22w xxxxxxxxxx035Millis. 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.
Ryan

0

RandomKlasa 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?

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.