[java] 랜덤 클래스 스레드는 안전합니까?

하나의 인스턴스를 공유하는 것이 유효한가요? Random여러 스레드간에 클래스 합니까? nextInt(int)특히 여러 스레드에서 호출하려면 ?



답변

여러 스레드에서 사용할 때 여전히 난수를 생성한다는 점에서 스레드로부터 안전합니다.

Sun / Oracle JVM 구현은 동기화 및 AtomicLong을 시드로 사용하여 스레드 간의 일관성을 향상시킵니다. 그러나 문서의 모든 플랫폼에서 보장되지는 않습니다.

특히 nextInt()호출 될 순서를 결정할 수 없기 때문에 이러한 보증을 요구하도록 프로그램을 작성하지 않습니다 .


답변

항상 그런 것은 아니지만 스레드로부터 안전합니다.

자세한 내용은 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 을 참조하십시오.


답변

문서에 따르면 Math.random () 은 여러 스레드에서 안전하게 사용할 수 있음을 보장합니다. 그러나 Random 클래스는 그렇지 않습니다. 그러면 직접 동기화해야한다고 생각합니다.


답변

예, Random은 스레드로부터 안전합니다. 이 nextInt()메서드 next(int)AtomicLong seed, nextseed(atomic long)을 사용하여 다음 시드를 생성하는 보호 된 메서드를 호출합니다 . AtomicLong시드 생성시 스레드 안전성을 위해 사용됩니다.


답변

말했듯이 스레드 저장이지만 이 기사 (링크 데드) java.util.concurrent.ThreadLocalRandom에 따라 사용하는 것이 현명 할 수 있습니다 . ThreadLocalRandom은 Random의 하위 클래스이기도하므로 이전 버전과 호환됩니다.

링크 된 기사는 서로 다른 Random 클래스의 프로파일 링 결과를 비교했습니다 : java.util.Random, java.util.concurrent.ThreadLocalRandom
java.lang.ThreadLocal<java.util.Random>. 결과는 ThreadLocalRandom의 사용이 가장 성능이 뛰어나고 ThreadLocal이 그 다음으로 가장 성능이 좋지 않은 것으로 나타났습니다.


답변

여러 스레드가 모두 동일한 Random을 사용할 수없는 이유는 없습니다. 그러나 클래스는 명시 적으로 스레드로부터 안전하지 않으며 시드를 통해 일련의 의사 난수를 유지합니다. 여러 스레드가 동일한 난수로 끝날 수 있습니다. 각 스레드에 대해 여러 개의 Random을 만들고 다르게 시드하는 것이 좋습니다.

편집 : 방금 Sun 구현이 AtomicLong을 사용하므로 스레드로부터 안전하다고 생각합니다 (Peter Lawrey (+1)도 언급했듯이).

EDIT2 : OpenJDK는 또한 시드에 AtomicLong을 사용합니다. 다른 사람들이 말했듯이 이것에 의존하는 것은 여전히 ​​좋지 않습니다.


답변

Random이 원자 변수를 사용한다고 가정하지 않고 문제를 처리 한 방법은 다음과 같습니다. currentTime * thread id미래의 시간이 같으면 여전히 무작위로 충돌 할 수 있지만 내 필요에 따라 충분히 드뭅니다. 충돌 가능성을 진정으로 피하려면 각 요청이 고유 한 시계 타임 스탬프를 기다리도록 할 수 있습니다.

/**
 * 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());
    }
};