1

I have a class

public class X {
    private volatile int value;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

Is it thread-safe or not? I think it does not thread-safe even if I add volatile keyword.

Finkelson
  • 2,921
  • 4
  • 31
  • 49

2 Answers2

2

The thread-safety can be expressed like "if the object of the class behaves exactly in the same way in multithreaded environment as in single-threaded environment, then it is thread-safe", or maybe instead "behaves exactly as" we could say "behaves correctly".

In your case correct behavior means that after calling setValue(N), a following getValue() returns N. In case you wouldn't use the volatile modifier, this would be true only in single-threaded environment: if you call setValue(N) on Thread1 then after you call getValue() on Thread2, then it won't necessarily return N. The problem is that Thread1 and Thread2 may be executed on separate CPU cores, and CPU cores usually don't read/write directly the shared memory: the two processors can have separate CPU caches, and the setValue(N) call may modify only the CPU-cached copy of the value member, therefore this change won't be immediately visible for the RAM. Furthermore, even if N is already available in the shared memory, the getValue() may read a cached - but obsolete - value from the second processor cache. Therefore the value change you perform on Thread1 may not be immediately visible on Thread2, so getValue() may return a deprecated value.

The volatile modifier solves it with its following 2 properties:

  • after writing a volatile value it won't only be stored in the CPU cache, but immediately flushed into the shared RAM
  • reading a volatile value will always read it from the memory, never from the CPU cache.
erosb
  • 2,943
  • 15
  • 22
0

To simply answer your question: you should use volatile when the variable will be accessed by multiple threads and you don't want/need to lock it. From the example your provided the get may present a problem in terms of 'thread safe' (see answer of erosb)

As extra: the usage of volatile is limited so I would strongly suggest you to use AtomicInteger which provides you both atomicity and volatility (AtomicInteger class stores its value field in a volatile variable).

adhg
  • 10,437
  • 12
  • 58
  • 94