Are static variables shared between threads?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Static variables are usually shared by all threads in the same process because the threads share the same memory space. That fact is simple, but it leads to a common mistake: shared does not mean safe. A static field gives every thread access to the same state, which is useful for caches and configuration, but dangerous for mutable counters or collections unless concurrency is handled explicitly.
Why Static Variables Are Shared
A static variable belongs to the class, not to an instance. In most runtime models, including Java and C#, all threads in one process can see the same class-level storage.
A Java example makes this obvious:
Every thread calling increment() touches the same counter field. There is not one copy per thread and not one copy per object.
Shared State Creates Race Conditions
The next step is the important one: counter++ is not atomic. It is a read, then a calculation, then a write. Two threads can interleave those steps and lose updates.
You might expect 200000, but in a real run the result can be smaller because increments were lost.
How To Make Shared Static State Safe
If multiple threads write shared static data, use synchronization or a thread-safe abstraction.
AtomicInteger is a good choice for simple counters. For more complex shared state, you may need synchronized, locks, or concurrent collections.
volatile Does Not Solve Everything
A frequent misunderstanding is that volatile makes shared state “thread-safe.” It does not. volatile helps with visibility, meaning one thread sees another thread’s most recent write more reliably. But it does not make compound operations such as incrementing atomic.
So this is still unsafe for counting:
If the problem is read-modify-write, use atomic operations or locking.
When You Need Per-Thread State Instead
Sometimes developers ask about static fields because they want a value accessible everywhere, but what they really need is a separate value per thread. In Java, ThreadLocal handles that.
The ThreadLocal reference is static, but the contained value is separate for each thread. That is a very different design from a shared static variable.
Common Pitfalls
- Assuming a shared static field is automatically thread-safe.
- Using
volatilefor operations that need atomicity. - Forgetting that mutable static collections also need synchronization discipline.
- Using static state when the real requirement is per-thread or per-request data.
Summary
- Static variables are generally shared between threads in the same process.
- Shared visibility does not make writes safe.
- Mutable shared static state needs locking, atomics, or concurrent data structures.
- '
volatilehelps with visibility, not compound updates.' - Use
ThreadLocalwhen you need one logical value per thread instead of one shared value.

