1

There is an example in JLS about the keyword volatile.

One thread repeatedly calls the method one, another thread calls the method two.

  class Test {
        static volatile int i = 0, j = 0;
        static void one() { i++; j++; }
        static void two() {
            System.out.println("i=" + i + " j=" + j);
        }
    }

This allows method one and method two to be executed concurrently, but guarantees that accesses to the shared values for i and j occur exactly as many times, and in exactly the same order, as they appear to occur during execution of the program text by each thread. Therefore, the shared value for j is never greater than that for i, because each update to i must be reflected in the shared value for i before the update to j occurs. It is possible, however, that any given invocation of method two might observe a value for j that is much greater than the value observed for i, because method one might be executed many times between the moment when method two fetches the value of i and the moment when method two fetches the value of j.

Some questions:

  • What does shared values mean?
  • In which scenario should we use volatile?(since "any given invocation of method two might observe a value for j that is much greater than the value observed for i")

I learned from other articles that if there is more than one core or processor (I think the point is more than one cache), an "unvolatile" value may cause problems.

What is the problem? And why?

wuyi
  • 227
  • 1
  • 17

2 Answers2

3

The shared values are the static int i,j as they can be shared between many different threads (that's the definition of static). You should use volatile when you have multiple threads accessing the same variable. There is same debate whether volatile should only be used when one thread writes to the value and others read it as operations such as i += 5 are not atomic unless you use AtomicInteger (which should be preferred although there is a higher overhead).

The reason you should use volatile when one thread writes to the value and one (or many) threads read from the value is because without the volatile keyword the thread will cache the value and will use the value from the cache which may not be consistent with the actual value. The volatile keyword forces every thread to not cache the value and access the actual memory location of the value instead.

M. Shaw
  • 1,742
  • 11
  • 15
  • **without the volatile keyword the thread will cache the value and will use the value from the cache which may not be consistent with the actual value.** Every thread has it's own cache? Where is the cache? – wuyi Aug 10 '15 at 02:37
  • @李博喜 every CPU has it's own cache. This is how modern CPUs work. – Peter Lawrey Aug 10 '15 at 03:53
  • CPU caches are synchronised. You don't need to worry about these. – curiousguy Aug 10 '15 at 20:21
1

A shared value in this context is a variable manipulated by several threads.

Access to non-volatile variables can be reordered by the implementation (compiler or CPU), so the results can be inconsistent with the "naively" expected results, that is, a sequential execution. With volatile, you have the guarantee that access to the shared variables are done serially, consistently with program order execution.

You need volatile when conflicting accesses to variables is done concurrently, without the protection of locks, semaphores, or other mutual exclusion primitives. Two operation on the same variable are conflicting if at least one is a write (read/write or write/write) and they aren't ordered by a mutual exclusion primitive or by program order.

curiousguy
  • 8,038
  • 2
  • 40
  • 58