What does it mean for a class to be thread-safe?

We often heard the question about whether a class is thread-safe. The answer can be complicated. Effective Java describes 5 levels of thread-safety:

  1. Immutable
  2. Thread-safe: multiple threads can access the same instance in any way without causing inconsistent state.
  3. Conditionally thread-safe: weaker than thread-safe in that some sequences of method calls need external synchronization. For example, for a class implementing Stack, the class implementation can do proper locking within individual methods like Push and Pop, but it still does not protect against multiple threads calling Push followed by Pop. In this case, the client needs to do synchronization.
  4. Thread-compatible: even weaker in that each method may need external synchronization, but it still allows client to write thread-safe code.
  5. Thread-hostile: no way for client to write thread-safe code. For example, if private static state access is not synchronized, there is no way for client to know and do synchronization on its own.

So a better question is: can the class be used in a thread-safe way? That is the reason that in general, a class needs to synchronize access to the static state, but not the instance state.