-
ThreadLocalRandom을 왜 사용해야할까?스터디/JAVA 2023. 11. 1. 23:51728x90
Random 클래스가 난수를 생성하는 방법
Random 클래스는 시드를 기반으로 난수를 생성합니다. 즉, 동일한 시드를 사용하면 동일한 난수를 반환합니다.
하지만 난수라는 개념 자체가 예측할 수 없는 값을 의미하므로, 동일한 시드에서 동일한 난수를 반환하는 것은 진정한 난수 생성과는 다소 거리가 있습니다. 이를 해결하기 위해, Random 클래스는 한 번 사용한 시드를 바탕으로 새로운 시드(newSeed)를 생성하여 다음 난수의 기반이 되도록 합니다.
protected int next(int bits) { AtomicLong seed = this.seed; long oldseed; long nextseed; do { oldseed = seed.get(); nextseed = oldseed * 25214903917L + 11L & 281474976710655L; } while(!seed.compareAndSet(oldseed, nextseed)); return (int)(nextseed >>> 48 - bits); }
CAS(Compare-And-Swap) 연산을 사용하여 현재 사용하려는 시드(oldSeed)가 다른 곳에서 이미 사용되었는지를 확인합니다. 만약 oldSeed가 다른 곳에서 변경되었다면, 이는 CPU 캐시 메모리의 시드 값과 RAM에 저장된 시드 값이 달라졌다는 의미이며, 즉 해당 시드가 이미 난수 생성에 사용되었음을 뜻합니다. 따라서 난수의 예측 가능성을 방지하기 위해, while문을 반복합니다.
경쟁 상태 발생
수백만 개의 요청이 동시에 들어온다고 가정하고, Random 클래스를 사용하여 난수를 생성한다고 하자. 이 경우, 수많은 요청 중 일부가 동일한 시드(seed)를 부여받을 확률이 높아집니다. 따라서 동일한 시드가 다른 곳에서 먼저 사용될 가능성도 커집니다.
이렇게 되면, 여러 스레드가 동시에 난수를 생성하려 할 때 동일한 시드를 사용하려고 시도하면서, CAS(Compare-And-Swap) 연산이 반복적으로 실패할 수 있습니다. 결과적으로, 여러 스레드가 반복적으로 while 루프를 돌며 새로운 시드를 찾는 상황이 발생할 수도 있습니다.
그렇게 되면... 아주 힘든 상황이 발생할 것이다. 🥹
Java에서는 이러한 상황을 고려하여 ThreadLocalRandom이라는 클래스를 만들었습니다.ThreadLocalRandom을 사용하자
ThreadLocalRandom 클래스는 Random 클래스에 발생할 수 있는 경쟁 상태를 해결하기 위해 각 스레드마다 생성된 인스턴스에 각각 seed를 설정해둡니다. 이렇게 하면 멀티 스레드 환경에서 동시에 난수를 발행한다고 해도 각 스레드마다 다른 seed를 사용하기 때문에 경합 문제도 발생하지 않고 난수도 생성할 수 있게 됩니다.
지금까지 Random 클래스에서 발생할 수 있는 문제와 그 해결책인 ThreadLocalRandom 클래스에 대해서 알아보았습니다.
감사합니다.728x90'스터디 > JAVA' 카테고리의 다른 글
불변 객체와 가비지 컬렉션의 관계 (0) 2024.08.22 Comparable과 Comparator는 언제 써야할까? (3) 2023.06.01 불변 객체(Immnutable Object)란?? (1) 2023.05.27 String vs StringBuilder vs StringBuffer (0) 2023.05.27 정적 팩토리 메서드 언제 사용해야할까? (1) 2023.05.23