|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 6 of 8
Volatility, that is, changeability, describes the situation where one thread changes a shared field variable's value and another thread sees that change. You expect other threads to always see a shared field variable's value, but that is not necessarily the case. For performance reasons, Java does not require a JVM implementation to read a value from or write a value to a shared field variable in main memory, or object heap memory. Instead, the JVM might read a shared field variable's value from a processor register or cache, collectively known as working memory. Similarly, the JVM might write a shared field variable's value to a processor register or cache. That capability affects how threads share field variables, as you will see.
Suppose a program creates a shared integer-field variable x whose initial value in main memory is 10. This program starts two threads; one thread writes to x, and the other reads x's value. Finally, this program runs on a JVM implementation that assigns each thread its own private working memory, meaning
each thread has its own private copy of x. When the writing thread writes 6 to x, the writing thread only updates its private working-memory copy of x; the thread does not update the main-memory copy. Also, when the reading thread reads from x, the returned value comes from the reading thread's private copy. Hence, the reading thread returns 10 (because a shared
field variable's private working-memory copies initialize to values taken from the main-memory counterpart), not 6. As a result,
one thread is unaware of another's change to a shared field variable.
A thread's inability to observe another thread's modification to a shared field variable can cause serious problems. For example,
last month's YieldDemo application contained a pair of shared field variables: finished and sum. For JVMs that support separate working memory for each thread, the main and main-created YieldDemo threads can have their own copies of finished and sum. As a result, the main thread's execution of finished = true; would not affect the YieldDemo thread's copy of that variable—and the YieldDemo thread would never terminate.
When you ran YieldDemo, you probably discovered that program eventually terminated. That implies your JVM implementation reads/writes main memory
instead of working memory. But if you found that the program did not terminate, you probably encountered a situation where
the main thread set its working memory copy of finished to true, not the equivalent main-memory copy. Also, the YieldDemo thread read its own working-memory copy of finished, and never saw true.
To fix YieldDemo's visibility problem (on those JVMs that support working memory), include Java's volatile keyword in the finished and sum declarations: static volatile boolean finished = false; and static volatile int sum = 0;. The volatile keyword ensures that when a thread writes to a volatile shared field variable, the JVM modifies the main-memory copy, not
the thread's working-memory copy. Similarly, the JVM ensures that a thread always reads from the main-memory copy.