the java memory model n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
The Java Memory Model PowerPoint Presentation
Download Presentation
The Java Memory Model

Loading in 2 Seconds...

play fullscreen
1 / 55

The Java Memory Model - PowerPoint PPT Presentation


  • 123 Views
  • Uploaded on

The Java Memory Model. JMM: SC intuition may fail. Application programmer supposes sequential consistent memory model The trace proves that the memory model is not sequential consistent (cycle of program order + value inheritance) The execution doesn’t violate the Java Memory Model.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'The Java Memory Model' - kermit


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide2

JMM: SC intuition may fail

  • Application programmer supposes sequential consistent memory model
  • The trace proves that the memory model is not sequential consistent (cycle of program order + value inheritance)
  • The execution doesn’t violate the Java Memory Model
operations defined in jmm
Operations defined in JMM
  • Abstractions of Java bytecodes
  • Concern to heap accesses
  • There are synchronization memory accesses
    • Locking monitor (while entering synchronized method or block), reading volatile variable (in the new JMM) and calling a start() on a thread works as acquire.
    • Unlocking monitor (while leaving synchronized method or block), writing volatile variable (in the new JMM) and calling a join() on a thread works as release.
the old operational jmm
The old (operational) JMM
  • Constrains inside a thread
  • Constrains between a thread and the main memory
  • General constrains
  • Locks
  • Volatile variables
  • Prescient stores

Execution engine

thread

use

assign

Working memory for each thread

lock

unlock

local copies

load store

write

read

Main memory

master copies

the jmm is changing
The JMM is changing
  • Problems of the old JMM:
    • Prohibits common compiler optimizations
    • Common programming idioms are not guaranteed to work (the double check idiom as an example)
    • It is hard for understanding
      • given in the operational form
  • The new JMM and the old code:
    • Correctly synchronized code would work OK
    • The code which is not correctly synchronized remains broken
the double check idiom
// Broken multithreaded version

// "Double-Checked Locking" idiom

class Foo {

private Helper helper = null;

public Helper getHelper() {

if (helper == null) synchronized(this) {

if (helper == null)

helper = new Helper();

}

return helper;

}

// other functions and members...

}

Used for implementing lazy initialization

May go wrong if the memory model is weaker than Sequential Consistency

a thread which invokes getHelper() could see a non-null reference to a helper object, but see the default values for fields of the helper object, rather than the values set in the constructor

There is no way to fix it for the common case

Failed on the old JMM

The double check idiom*

* By http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

the double check idiom how to solve the problem in java
The double check idiom: how to solve the problem in Java?
  • Use permanent synchronization
    • Common method not only for Java
  • Use static singletons
    • The semantics of Java guarantee that the static field will not be initialized until the field is referenced, and that any thread which accesses the field will see all of the writes resulting from initializing that field.
  • Double checking will work for 32-bit primitive values
    • Although the double-checked locking idiom cannot be used for references to objects, it can work for 32-bit primitive values
the double check idiom how to solve the problem in java continue
The double check idiom: how to solve the problem in Java? (continue)
  • Use Thread Local Storage (the solution of Alexander Terekhov )
    • Each thread keeps a thread local flag to determine whether that thread has done the required synchronization.
  • The new JMM makes it possible to fix the double-checked locking using volatile
    • Declare the helper field to be volatile
    • Is effective if volatile synchronization is cheaper than the explicit synchronization (by synchronized)
  • Use final fields
    • Make helper immutable
requirements to the new jmm by s adve
Requirements to the new JMM(by S. Adve)
  • SC for data-race-free programs
  • Safety / security for programs with data races
  • Optimizations must be allowed
  • Understandability
features of the new jmm
Features of the new JMM
  • Total order of synchronization actions, consistent with program order
  • Happens – before consistency (see below)
  • For each execution it must be possible to (virtually) commit all actions in some total order
why formal jmm definition
Why formal JMM definition ?
  • JVMs produced by different vendors must be formally estimated correct / incorrect
  • Automatic verification needs formal model
the project of the new jmm
The project of the new JMM
  • The new JMM would go into operation in Tiger (1.5) release of Java
  • The discussion continues, but the main ideas are just advertised
  • The current status: two concurrent groups of experts – (1) Manson and Pugh (University of Maryland) and (2) Adve (University of Illinois at Urbana-Champaign) has come to the agreement and proposed their “unified” model
the new jmm happens before order
The new JMM: happens-before order
  • SW (synchronized with) order – from release action, preceding in the total synchronization order, to subsequent acquire action on the same monitor / volatile variable
  • HB = SW U PO
roach motel
Roach motel
  • It is generally legal to reorder a normal memory access and a following acquire action, or a release action and a following normal memory access. This has been referred to as “roach motel” semantics: variable accesses can be moved into a synchronization block, but cannot, in general, move out
useless synchronization may be removed
Useless synchronization may be removed

Initially, A == B ==0

  • Lock acquisition on thread-local objects
  • Reacquisition of a lock on an object on which a thread already has a lock
  • Other cases detected by compiler analyses

May observe r3 = 1 and r4 = 0

happens before order sw
Happens-before order: SW
  • An unlock action on monitor m synchronizes-with all subsequent (in synchronization order) lock actions on m
  • A write to volatile variable v synchronizes-with all subsequent reads of v by any thread
  • An action that starts a thread synchronizes-with the first action in the thread it starts
  • The final action in a thread T1 synchronizes-with any action in another thread T2 that detects that T1 has terminated (isAlive, join)
synchronizes with continue
Synchronizes-with (continue)
  • If thread T1 interrupts thread T2, the interrupt by T1 synchronizes-with any point where any other thread (including T2) determines that T2 has been interrupted
  • The write of the default value (zero, false or null) to each variable synchronizes-with the first action in every thread
  • There is a happens-before edge from the end of a constructor of an object to the start of a finalizer for that object
happens before consistency
Happens-before consistency
  • Read must not precede by happens-before to the Write whose value it reads
  • Between Write W and its corresponding Read R may not be other write W’ to the same variable such that their order by happens-before: W → W’ → R
  • Problem: happens-before consistency doesn’t provide SC for correctly synchronized programs
  • Problem: happens-before consistency doesn’t provide safety guarantees
correctly synchronized program
Correctly synchronized program
  • The program is correctly synchronized if all possible SC executions of the program haven’t data races
  • JMM is desired to guarantee that correctly synchronized program would always run SC
    • All SC executions haven’t data races => the program haven’t non-SC executions
happens before consistency doesn t guarantee sc for correctly synchronized programs
Happens-before consistency doesn’t guarantee SC for correctly synchronized programs
  • The program hasn’t synchronization actions!!!
  • But: some accesses to shared variables disappear in all SC executions (y = 1, x = 1), therefore in all SC executions the program has not data races – formally: correctly synchronized
  • HB consistency doesn’t work: may be non-SC executions
safety guarantees needed for incorrectly synchronized programs
Safety guarantees needed for incorrectly synchronized programs
  • No out-of-thin-air reads
  • Type safety
  • Non-intrusive reads
    • When incorrectly synchronized reads are added to a correctly synchronized program (not altering semantics – debugging, etc.), the resulting program should still have sequentially consistent semantics, other than for the values seen by those reads
  • Causality
    • Prevents out-of-thin-air
no out of thin air intuition
No out-of-thin-air : intuition
  • Why causal loops may appear?
    • programs may speculatively perform a write, aborting and restarting things if, eventually, we don't commit/verify the write.
    • But in a multithreaded context, such speculation can wind up justifying itself : we may use static analysis and determine that there is some way to continue the execution such that the action could occur; then we can speculate that the event occurs in a way that allows the event to self-justify itself
causality
Causality
  • Defines when reads can see future writes
  • JMM intuition:
    • If a write is absolutely certain to be performed in all executions, it may be seen early
    • If a write cannot occur unless it is seen by an earlier read, it cannot be seen by an earlier read
causality the essence of the formal definition
Causality – the essence of the formal definition
  • Each execution E must be derived by the series of well-formed (prefix) executions Ei.Ei may contain committed and not committed actions
  • An execution is well-formed if it is happens-before consistent, has total order on sync actions, obeys intra-thread semantics and some weak fairness of sync actions
  • Each next execution Ei+1 contains all actions of the previous execution Ei
  • Committed actions cannot un-commit in the next execution
causality continue
Causality - continue
  • Reads that still haven’t committed must see only writes that happens-before
  • Committed reads must see writes just committed on previous steps
  • The value seen by not-committed read may change in the next (prefix) execution
  • Commitment “freezes” the value
  • Finally, in E all actions must be committed
causality strength
Causality - strength
  • Enough weak: writes may commit presciently
    • Other words, writes may commit when happens-before reads wet aren’t “frozen” by commitment.
  • Enough strong
    • Correctly synchronized programs has SC behavior (commitment order must preserve intra-thread semantics, therefore in the above example of correctly synchronized program actions cannot be reordered)
    • The total commitment order prevents causal loops. On each step action a whether depends on previously committed one or a is the read depending on the write w that happens-before (and, therefore, w cannot depend on a).
an approximation of the jmm for the programmers lrc
An approximation of the JMM for the programmers : LRC
  • Monitors synchronization – LRC behavior
  • Volatile synchronization – was discussed, recently established LRC behavior, too
  • Total order over all synchronization actions

Core JMM

=

+

LRC

Causality

volatile synchronization
Volatile synchronization
  • For each volatile, there is a total order over all accesses to that volatile.Question: how volatile accesses influence on the ordering of the ordinary data accesses?
    • Strong interpretation:

There is a happens-before (or release/acquire) relationship from each write to each latter read of that volatile.

    • Weak interpretation:

There is a happens-before (or release/acquire) relationship from each write to each latter read of that volatile that sees that write.

  • Some experts argued that weak interpretation is cheaper and it is sufficient for correctly synchronized code. However, expert group have agreed to adopt the strong semantics for volatiles.
volatile synchronization examples
Volatile synchronization: examples

Initially, x = y = v = 0

v is a volatile variable

Initially, x = y = v = 0

v is a volatile variable

Behavior in question: r1 == r3 == 1 Decision: Allowed under the weak interpretation, forbidden under the strong interpretation

Behavior in question: r1 = 1, r2 = 2, r3 = 2, r4 = 0Decision:Allowed under the weak interpretation, forbidden under the strong interpretation for volatile

causality test cases for jsr 133 draft explanation on examples
Causality Test Cases (for JSR-133 draft):explanation on examples*

Causality test case 1

Initially, x = y = 0

Behavior in question: r1 == r2 == 1 Decision: Allowed, since interthread compiler analysis could determine that x and y are always non-negative, allowing simplification of r1 >= 0 to true, and allowing write y = 1 to be moved early.

Causality test case 2

Initially, x = y = 0

Behavior in question: r1 == r2 == r3 == 1 Decision: Allowed, since redundant read elimi-nation could result in simplification of r1 == r2 to true, allowing y = 1 to be moved early.

Notes: In SC executions, both reads of x always return the same value

* From the JMM mail list: http://www.cs.umd.edu/~pugh/java/memoryModel

causality test cases continue
Causality Test Cases (continue)

Causality test case 3

Initially, x = y = 0

Behavior in question: r1 == r2 == r3 == 1 Decision: Allowed, since redundant read elimi-nation could result in simplification of r1 == r2 to true, allowing y = 1 to be moved early. Notes: Same as test case 2, except there are SC executions in which r1 != r2

Causality test case 4

Initially, x = y = 0

Behavior in question: r1 == r2 == 1 Decision: Forbidden: values are not allowed to come out of thin air

causality test cases continue1
Causality Test Cases (continue)

Causality test case 5

Initially, x = y = z = 0

Behavior in question: r1 == r2 == 1, r3 == 0 Decision: Forbidden: values are not allowed to come out of thin air, even if there are other executions in which the thin-air value would have been written to that variable by some not out-of-thin air means.

Causality test case 6

Initially, A = B = 0

Behavior in question: r1 == r2 == 1 Decision: Allowed. Intrathread analysis could determine that thread 2 always writes 1 to A and hoist the write to the beginning of thread 2.

causality test cases continue2
Causality Test Cases (continue)

Causality test case 7

Initially, x = y = z = 0

Behavior in question: r1 = r2 = r3 = 1. Decision: Allowed. Intrathread transformations could move r1 = z to after the last statement in thread 1, and x = 1 to before the first statement in thread 2.

Causality test case 8

Initially, x = y = 0

Behavior in question: r1 = r2 = 1

Decision: Allowed. Interthread analysis could determine that x and y are always either 0 or 1, and thus determine that r2 is always 1. Once this determination is made, the write of 1 to y could be moved early in thread 1.

causality test cases continue3
Causality Test Cases (continue)

Causality test case 9

Initially, x = y = 0

Behavior in question: r1 = r2 = 1

Decision: Allowed. Similar to test case 8, except that the x is not always 0 or 1. However, a compiler might determine that the read of x by thread 2 will never see the write by thread 3 (perhaps because thread 3 will be scheduled after thread 1). Thus, the compiler can determine that r1 will always be 0 or 1.

Causality test case 9a

Initially, x = 2, y = 0

Behavior in question: r1 = r2 = 1

Decision: Allowed. Similar to test case 8, except that the x is not always 0 or 1. However, a compiler might determine that thread 3 will always execute before thread 1, and that therefore the initial value of 2 will not be visible to the read of x in thread 1. Thus, the compiler can determine that r1 will always be 0 or 1.

slide35

Causality Test Cases (continue)

Causality test case 10

Initially, x = y = z = 0

Behavior in question:

r1 == r2 == 1, r3 == 0.

Decision: Forbidden. This is the same as test case 5, except using control dependences rather than data dependences.

causality test cases continue4
Causality Test Cases (continue)

Causality test case 11

Initially, x = y = z = 0

Behavior in question: r1 = r2 = r3 = r4 = 1

Decision: Allowed. Reordering of independent statements can transform the code, after which the behavior in question is SC.

Notes: This is similar to test case 7, but longer

Causality test case 12

Initially, x = y = 0; a[0] = 1, a[1] = 2

Behavior in question: r1 = r2 = r3 = 1

Decision: Disallowed. Since no other thread accesses the array a, the code for thread 1 should be equivalent to: r1 = x; a[r1] = 0; if (r1 == 0) r2 = 0 else r2 = 1 y = r2 With this code, it is clear that this is the same situation as test 4.

causality test cases continue5
Causality Test Cases (continue)

Causality test case 13

Initially, x = y = 0

Behavior in question: r1 = r2 = 1

Decision: Disallowed. In all sequentially consistent executions, no writes to x or y occur and the program is correctly synchronized. The only SC behavior is

r1 == r2 == 0.

Causality test case 14

Initially, a = b = y = 0, y is volatile

Behavior in question: r1 == r3 = 1; r2 = 0

Decision: Disallowed. In all sequentially consistent executions, r1 = 0 and the program is correctly synchronized. Since the program is correctly synchronized in all SC executions, no non-sc behaviors are allowed.

causality test cases continue6
Causality Test Cases (continue)

Causality test case 15

Initially, a = b = x = y = 0, x and y are volatile

Behavior in question: r0 == r1 == r3 = 1; r2 == 0

Decision: Disallowed. In all sequentially consistent executions, r1 = 0 and the program is correctly synchronized. Since the program is correctly synchronized in all SC executions, no non-sc behaviors are allowed.

Causality test case 16

Initially, x = y = 0

Behavior in question:

r1 == 2; r2 == 1

Decision: Allowed

Not coherent

causality test cases continue7
Causality Test Cases (continue)

Causality test case 17

Initially, x = y = 0

Behavior in question:

r1 == r2 == r3 == 42

Decision: Allowed. A compiler could determine that at r1 = x in thread 1, it must be legal to read x and see the value 42. Changing r1 = x to r1 = 42 would allow y = r1 to be transformed to y = 42 and performed earlier, resulting in the behavior in question.

Causality test case 18

Initially, x = y = 0

Behavior in question: r1 == r2 == r3 == 42

Decision: Allowed. A compiler could determine that the only legal values for x are 0 and 42. From that, the compiler could deduce that r3 != 0 implies r3 = 42. A compiler could then determine that at r1 = x in thread 1, it must be legal to read x and see the value 42. Changing r1 = x to r1 = 42 would allow y = r1 to be transformed to y = 42 and performed earlier, resulting in the behavior in question.

causality test cases continue8
Causality Test Cases (continue)

Causality test case 19

Initially, x = y = 0

Behavior in question: r1 == r2 == r3 == 42

Decision: Allowed. This is the same as test case 17, except that thread 1 has been split into two threads.

Causality test case 20

Initially, x = y = 0

Behavior in question: r1 == r2 == r3 == 42

Decision: Allowed. This is the same as test case 18, except that thread 1 has been split into two threads.

slide41

Additional Test Cases for the Unified Model

Causality test case U2

Initially, a = b = y = 0

Behavior in question: r1 == r3 == 1; r2 == 0

Decision: Prohibited.

Test case U1

Initially, x = 1 and y = 0

Behavior in question: r1 == r2 == 2

Decision: Prohibited.

slide42

Additional Test Cases (continue)

Causality test case U3

Initially, a = b = c = d = 0

Behavior in question: r1 == r3 == r4 ==1; r2 == 0

Decision: Allowed. Result of inlining of U4 (see below)

Causality test case U3

Initially, a = b = y = 0

Behavior in question: r1 == r3 == 1; r2 == 0

Decision: Prohibited.

additional test cases continue
Additional Test Cases (continue)

Causality test case U4

Initially, a = b = c = d = 0

Behavior in question: r1 == r3 == r4 == 1; r2 == 0

Decision: Prohibited.

slide44

Additional Test Cases (continue)

Causality test case U6

Initially, x = y = z = 0, z is volatile

Behavior in question: r1 == r2 == 1; r3 == 0

Decision: Prohibited.

slide45

Additional Test Cases (continue)

Causality test case U7

Initially, x = y = z = 0

Behavior in question: r1 == 1; r2 == r3 == 2

Decision: Allowed.

above the core jmm
Above the core JMM
  • Final field Semantic
  • Special cases
    • Write Protected Fields
    • Word Tearing
  • Double and long variables
    • Not guaranteed to be atomic
  • Fairness
  • Wait Sets and Notification
  • Sleep and yield
    • Haven’t any synchronization semantics
  • Finalization
final field semantics
Final Field Semantics
  • The value of a final field is not intended to change
  • Data race tolerate
    • Do not need synchronization if the references to the containing objects are not made visible to other threads during construction
  • Minimal cost when reading final field
final fields correctly published references
Final fields: correctly published references

f is a final field; its default value is 0

  • If a reference to the object containing the final field is shared with other threads between the initial construction of the object and when deserialization changes the final fields of the object, guarantees for the final field don’t work

Assume r2, r4 and r6 do not see value null. r3 and r5 can be 0 or 42, and r7 must be 42

final fields exceptional cases
Final fields: exceptional cases
  • It is planned to allow reflection to change final fields, assuming the appropriate security permissions; is needed for situations such as deserialization
  • Special rules would be applied while optimizing such code
    • Executing a block of code in a final field safe context (treated as a separate thread)
special cases
Special cases
  • Write Protected Fields
    • System.in, System.out, System.err: final static fields, but may be changed by special methods
  • Word Tearing
    • Not allowed: updates to one field or element do not interact with reads or updates of any other field or element
fairness
Fairness

Initially, v is volatile and v is false

  • JMM has weak fairness guarantees for synchronization actions. Only a finite number of synchronization actions may occur before a given synchronization action occurs in the synchronization order

If we observe the print message

from Thread 2, and no other

threads are running, Thread 1 must see the write to v and terminate

fairness implementation issues
Fairness: implementation issues
  • If there exists some thread that is able to make progress, some thread will make progress
  • Compilers cannot, in general, hoist volatile reads out of potentially infinite loops
  • Compilers cannot, in general, reorder synchronization actions and externally visible actions
wait sets and notification
Wait Sets and Notification
  • Every object has an associated wait set. A wait set is a set of threads
  • Elementary actions that add threads to and remove threads from wait sets are atomic
  • Wait sets are manipulated through Object.wait, Object.notify, Object.notifyAll
  • Wait sets are affected by interruption
    • Notifications cannot be lost due to interrupts
  • Sleeping and joining have properties derived from those of wait and notification actions
interaction of waits notification and interruption
Interaction of waits, notification and interruption
  • If a thread is both notified and interrupted while waiting, it may either:
    • Return normally from wait, while still having a pending interrupt
    • Return from wait by throwing an InterruptedException
  • Assume that a set S of threads is in the wait set of a monitor M, and another thread performs a notify on M. Then either
    • At least one thread in S returns normally from wait (without throwing InterruptedException), or
    • All of the threads in S must exit wait by throwing InterruptedException
further reading
Further reading
  • JMM web page http://www.cs.umd.edu/~pugh/java/memoryModel/
  • java.util.concurrent package http://g.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html