Why ThreadLocalRandom Uses Unsafe: Performance, Safety, and Memory Insights
This article examines Java's Random performance issues in high‑concurrency environments, explains how ThreadLocalRandom leverages sun.misc.Unsafe for lock‑free per‑thread seeds, and explores the associated memory layout, safety concerns, and practical code examples.
Introduction: The author needed random numbers and explored java.util.Random, then ThreadLocalRandom and Unsafe for performance.
Random performance issue
Using a shared Random instance can cause contention in high‑concurrency web services because Random updates its seed with CAS, leading to thread blocking.
ThreadLocalRandom
JDK provides ThreadLocalRandom to avoid this contention. Although its name suggests use of ThreadLocal, its implementation relies heavily on sun.misc.Unsafe to manipulate a per‑thread seed stored directly in the Thread object.
Core code
UNSAFE.putLong(t = Thread.currentThread(), SEED, r = UNSAFE.getLong(t, SEED) + GAMMA);
Thread t = Thread.currentThread();
long r = UNSAFE.getLong(t, SEED) + GAMMA;
UNSAFE.putLong(t, SEED, r);The code reads the current thread’s seed, adds a constant, and writes it back, similar to a map get/set but using raw memory offsets.
Unsafe methods
Unsafe provides native methods public native long getLong(Object o, long offset) and
public native void putLong(Object o, long offset, long value)that read and write eight bytes at a given memory offset without safety checks.
These operations are “unsafe” because they can corrupt memory if the offset or value is incorrect, potentially causing JVM fatal errors.
Example of unsafe misuse
public static void main(String[] args) throws Exception {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
Test test = new Test();
test.ttt = "12345";
unsafe.putLong(test, 12L, 2333L);
System.out.println(test.value);
}This code overwrites a String field with a long, leading to a fatal JVM error.
Why Unsafe is used in ThreadLocalRandom
ThreadLocalRandom stores a per‑thread seed in the private field threadLocalRandomSeed of java.lang.Thread. The offset of this field is obtained via Unsafe.objectFieldOffset, allowing fast, lock‑free updates without exposing public getters/setters, preserving encapsulation.
Questions raised
Why does ThreadLocalRandom need Unsafe instead of ordinary get/set methods?
How is the memory layout of a Java object determined (object header, compressed oops, field offsets)?
Conclusion
Understanding the underlying implementation of core JDK classes helps avoid hidden pitfalls and can improve performance.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
