Why is this class not thread safe?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Understanding Thread Safety in Java Classes
Java's multithreaded environment allows multiple threads to run concurrently. While this feature is powerful, enabling more efficient utilization of resources and better application performance, it also comes with challenges—especially concerning thread safety.
Thread safety is a critical consideration when developing classes that can be accessed by multiple threads simultaneously. A class is said to be "thread-safe" if its methods and operations are carried out consistently and correctly, even when accessed by multiple threads at the same time.
Why a Class Might Not Be Thread-Safe
To understand why a class may not be thread-safe, it's crucial to delve into various symptoms and technical reasons that can lead to this situation:
- Race Conditions: Occurs when two or more threads attempt to modify shared data simultaneously, leading to unpredictable outcomes. For instance, if two threads increment a counter, they might read the same initial value and then both write back an incremented value, only for one increment to be lost.
- Data Corruption: Accessing shared mutable data without proper synchronization can result in data corruption. If a class does not provide adequate locking mechanisms, the internal state may become inconsistent.
- Visibility Issues: Changes made by one thread to a shared variable may not be visible to other threads due to caching mechanisms and the Java Memory Model (JMM). Without proper use of the
volatilekeyword or synchronized blocks, threads might read stale data. - Deadlocks: Occurs when two or more threads are blocked forever, each waiting on the other. Classes that improperly implement synchronized methods or blocks can cause a deadlock.
- Atomicity Violations: If operations that need to be atomic are not implemented correctly, it might lead to violations. For example, incrementing a variable is not atomic by default, as it involves reading, adding, and writing back to the variable.
Example of a Non-Thread-Safe Class
Consider a simple counter class:
- Synchronization: Using the
synchronizedkeyword ensures mutual exclusion and memory visibility. - **Locks from
java.util.concurrent**: ReentrantLock offers more control and flexibility compared to synchronized blocks/methods. - Atomic Variables: Use classes like
AtomicIntegerfor operations that need to be atomic.
Related reading
- Why is this code getting faster when I'm using way more threads than my CPU has cores?
- Why is Thread.Sleep so harmful
- Why is UncaughtExceptionHandler not called by ExecutorService?
- Why is volatile not considered useful in multithreaded C or C programming?
- Why is Thread not an abstract class and start not final?
- Why is TreeSet Iteration On instead of Onlogn?
- why isn't numpy.mean multithreaded?
- Why isn't there an asynchronous file delete in .net?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.