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.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why ThreadLocalRandom Uses Unsafe: Performance, Safety, and Memory Insights

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

unsaferandomThreadLocalRandom
Java Backend Technology
Written by

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!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.