...
In this ordering, r1
and r2
read the values of a
and b
written from step 3 and 4, before the steps are executed.
Even if statements execute in the expected order, caching can prevent the latest values from being reflected in the main memory. Such counter-intuitive behavior necessitates the sequential consistency property.
Wiki Markup |
---|
2. [Sequential consistency|BB. Definitions#sequential consistency]: "The fact that we allow a read to see a write that comes later in the execution order can sometimes thus result in unacceptable behaviors." \[[JLS 05|AA. Java References#JLS 05]\]. In such cases, sequential consistency is required. This condition ensures that the compiler does not optimize away or reorder any statements. It also ensures that each operation is atomic and immediately visible to other threads. This makes it easy for a programmer to follow the logic, however, introduces a performance penalty. Synchronization guarantees sequential consistency and so does use of the {{volatile}} keyword. |
Program order is the execution order that is expected when a single thread is running the statements sequentially, as written in a method. Even if statements execute in the expected order (program order), caching can prevent the latest values from being reflected in the main memory.
2. Sequential consistency: This property provides a very strong guarantee that the compiler will not optimize away or reorder any statements. It guarantees that the program is free from data races. It also ensures that each access is atomic and immediately visible to other threads.
The use of sequential consistency as the sole memory model mechanism makes it easy for a programmer to follow the logic, however, introduces a performance penalty. Implementing synchronization correctly guarantees sequential consistency and is consequently, a more expensive operation than using volatile
variables which guarantee a weaker form of sequential consistency.
Volatile read and write operations cannot be reordered with respect to each other and in addition, as required by the JMM, volatile read and write operations are also not reordered with respect to operations on non-volatile variables.
Using volatile
variables guarantees a weaker form of sequential consistency because statements prior to a volatile
access appear to occur in program order with respect to the statement that writes to the volatile
variable. The previous statements may, however, be freely reordered and may not be sequential consistent with respect to each other. This makes the cost of using volatile
cheaper than synchronizing every piece of code.
Wiki Markup |
---|
"Finally, note that the actual execution order of instructions and memory accesses can be in any order as long as the actions of the thread appear to that thread as if program order were followed, and provided all values read are allowed for by the memory model. This allows the programmer to fully understand the semantics of the programs they write, and it allows compiler writers and virtual machine implementors to perform complex optimizations that a simpler memory model would not permit." \[[JPL 06|AA. Java References#JPL 06]\]. |
A write to a volatile
field happens-before every subsequent read of that field. Statements that occur before the write to the volatile
field also happen-before the read of the volatile
field. Declaring , from possibly another thread. Consequently, declaring a variable volatile
guarantees that writes are always visible to subsequent reads of the variable from any thread. It also ensures sequential consistency, in that, volatile read and write operations cannot be reordered with respect to each other and in addition, as required by the JMM, volatile read and write operations are also not reordered with respect to operations on non-volatile variablesWhen reading the volatile
variable, the other thread will also see statements occurring before the write to the volatile
variable, to have already executed with prior occurrences of volatile
and non-volatile fields assuming the assigned values.
Noncompliant Code Example
...
Wiki Markup |
---|
\[[JLS 05|AA. Java References#JLS 05]\] [Chapter 17, Threads and Locks|http://java.sun.com/docs/books/jls/third_edition/html/memory.html], section 17.4.5 Happens-before Order, section 17.4.3 Programs and Program Order, section 17.4.8 Executions and Causality Requirements
\[[Tutorials 08|AA. Java References#Tutorials 08]\] [Java Concurrency Tutorial|http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html]
\[[Lea 00|AA. Java References#Lea 00]\] Sections, 2.2.7 The Java Memory Model, 2.2.5 Deadlock, 2.1.1.1 Objects and locks
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 66: Synchronize access to shared mutable data
\[[Goetz 06|AA. Java References#Goetz 06]\] 3.4.2. "Example: Using Volatile to Publish Immutable Objects"
\[[JPL 06|AA. Java References#JPL 06]\] 14.10.3. "The Happens-Before Relationship"
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 667|http://cwe.mitre.org/data/definitions/667.html] "Insufficient Locking", [CWE ID 413|http://cwe.mitre.org/data/definitions/413.html] "Insufficient Resource Locking", [CWE ID 366|http://cwe.mitre.org/data/definitions/366.html] "Race Condition within a Thread", [CWE ID 567|http://cwe.mitre.org/data/definitions/567.html] "Unsynchronized Access to Shared Data" |
...