the java memory model - rice universityjohnmc/comp522/lecture-notes/comp522-… · use volatile to...
TRANSCRIPT
TheJavaMemoryModelAuthors:JeremyManson,WilliamPugh,SaritaV.AdvePresenter:KerenZhouCOMP522
WhyJavaneedsawell-formedmemorymodel• Javasupportsthreadsrunningonsharedmemory• Javamemorymodeldefinesmulti-threadedJavaprogramsemantics• Keyconcerns:Javamemorymodelspecifieslegalbehaviorsandprovidessafetyandsecurityproperties
3/26/19 2
WhyshouldwecareaboutJavaMemoryModel• Aprogrammershouldknow• Juniorlevel
• Usemonitor,locks,andvolatile properly• LearnsafetyguaranteesofJava
• Intermediatelevel• Reasonthecorrectnessofconcurrentprograms• Useconcurrentdatastructures(e.g ConcurrentHashMap)
• Expertlevel• Understandandoptimizeutilitiesinjava.util.concurrent
• AbstractExecutorService• Atomicvariables
3/26/19 3
Createasingletontogetastaticinstance• Singleton:onlywantasingleinstanceinaprogram• Database• Logging• Configuration
3/26/19 4
public class Instance {private static Instance instance;public static Instance getInstance() {if (instance == null)instance = new Instance();
return instance;}
}
12345678
Thesimplesingletonisthread-unsafe
3/26/19 5
public class Instance {private static Instance instance;public static Instance getInstance() {if (instance == null)instance = new Instance();
return instance;}
}
12345678
Threads
T0
T1
Line4
Line4
Line5
Line5
Line6
Line6
getInstance
getInstance
Time Line
Createtwoinstancesatthesametime!
Usesynchronizedkeyword
3/26/19 6
• Javasynchronized keywordcanbeusedindifferentcontexts• Instancemethods• Codeblocks• Staticmethods
• Onlyonethreadcanexecuteinsideastaticsynchronizedmethodperclass,irrespectiveofthenumberofinstancesithas.
Thesynchronizedsingletonhaslowperformance
3/26/19 7
public class Instance {private static Instance instance;public synchronized static Instance getInstance() {if (instance == null)instance = new Instance();
return instance;}
}
12345678
Threads
T0
T1
Line4 Line5 Line6getInstance
getInstance
Time Line
Line4 Line5 Line6
Usedouble-checkedlocktomakeitmoreefficient• Motivation:Intheearlydays,thecostofsynchronizationcouldbequitehigh• Idea:Avoidthecostlysynchronizationforallinvocationsofthemethodexceptthefirst• Solution:• Firstcheckiftheinstanceisnullornot• Ifinstanceisnull,enteracriticalsectiontocreatetheobject• Ifinstanceisnotnull,returninstance
3/26/19 8
Doublechecked-lockimplementation
3/26/19 9
public class Instance {private static Instance instance;public static Instance getInstance() {if (instance == null) {synchronized (Instance.class) {if (instance == null) {
instance = new Instance();}
}}return instance;
}}
12345678910111213
Howdouble-checkedlockgoeswrong• Briefanswer:instructionreorder• SupposeT0isinitializingwiththefollowingthreesteps1) mem=allocate();//AllocatememoryforSingleton2) ctorSingleton(mem);//Invokeconstructor3) object.instance =mem;//initializeinstance.
• Whatifstep2isinterchangedwithstep3?• AnotherthreadT1mightseetheinstancebeforebeingfullyconstructed
3/26/19 10
Athreadreturnsanobjectthathasnotbeenconstructed
3/26/19 11
public static Instance getInstance() {if (instance == null) {synchronized (UnsafeInstance.class) {if (instance == null) {
instance = new Instance();}
}}return instance;
}
3456789101112
Threads
T0
T1
Line4
Line4
Line5
Line11
Line6getInstance
getInstance
Time Line
Line7
mem = allocate();object.instance = mem;ctorSingleton(mem);
T1returnsbeforeconstructorcompletes!
Usevolatiletoavoidreordering
• Thebehaviorofvolatile differssignificantlybetweenprogramminglanguages• C/C++
• Volatilekeywordmeansalwaysreadthevalueofthevariablememory
• Operationsonvolatilevariablesarenotatomic• Cannotbeusedasaportablesynchronizationmechanism
• Java• Preventreordering• DeriveasynchronizationorderontopofJavaMemoryModel
3/26/19 12
Usevolatiletoavoidreordering
• Java’svolatile wasnotconsistentwithdevelopersintuitions• TheoriginalJavamemorymodelallowedforvolatilewritestobereorderedwithnonvolatilereadsandwrites
• UnderthenewJavamemorymodel(fromJVMv1.5),volatilecanbeusedtofixtheproblemswithdouble-checkedlocking
3/26/19 13
Javamemorymodelhistory
• 1996:AnOptimizationPatternforEfficientlyInitializingandAccessingThread-safeObjects,DouglasC.Schmidt andetc.• 1996:TheJavaLanguageSpecification,chapter17,JamesGoslingandetc.• 1999:FixingtheJavaMemoryModel,WilliamPugh• 2004:JSR133---JavaMemoryModelandThreadSpecificationRevision
3/26/19 14
Review:sequentialconsistency
• Totalorder:Memoryactionsmustappeartoexecuteoneatatimeinasingletotalorder• Programorder:Actionsofagiventhreadmustappearinthesameorderinwhichtheyappearintheprogram
3/26/19 15
Review:sequentialconsistencyviolation
3/26/19 16
r2=xy=1
r1=yx=2
Thread1 Thread2
Initialconditions:x=y=0
Finalresults: r2==2andr1==1?
Decision:Disallowed.Violatessequentialconsistency
12
34
Circulardependency!
Interthreadsdependency
Intrathreaddependency
Javamemorymodelbalancesbetweenperformanceandsafety• Sequentialconsistency• Easytounderstand• Restrictstheuseofmanycompilerandhardwaretransformations
• Relaxedmemorymodels• Allowmoreoptimizations• Hardtoreasonaboutthecorrectness
3/26/19 17
Javamemorymodelhidesunderlyinghardwarememorymodel
3/26/19 18
JavaProgram
High-levelLanguageMemoryModel
JavaCompiler
JavaRuntime
HardwareMemoryModel
TSO, Power’s weak model, …
Javadefinesdata-race-freemodel
• Dataraceoccurswhentwothreadsaccessthesamememorylocation,atleastoneoftheaccessesisawrite,andthereisnointerveningsynchronization• Adata-race-free Javaprogramguaranteessequentialconsistency(Correctlysynchronized)
3/26/19 19
Anotherdefinitionofdata-racefromJavaMemoryModel’sperspective• Twoaccessesx andy formadataraceinanexecutionofaprogramiftheyarefromdifferentthreads,theyconflict,andtheyarenotorderedbyhappens-before
3/26/19 20
Happens-beforememorymodel
• AsimplerversionthanthefullJavaMemoryModel• Happens-beforeorder
• Thetransitiveclosureofprogramorderandthesynchronizes-withorder
• Happens-beforeconsistency• Determinesthevaluethatanon-volatilereadcansee
• Synchronizationorderconsistency• Determinesthevaluethatavolatilereadcansee
• SolvespartoftheJavamysteriousproblems
3/26/19 21
Programorderdefinition
• TheprogramorderofthreadT isatotalorderthatreflectstheorderinwhichtheseactionswouldbeperformedaccordingtointra-threadsemanticsofT• Ifx andy areactionsofthesamethreadandx comesbeforey inprogramorder,thenhb(x,y)(i.e.x happens-beforey)
3/26/19 22
Eliminateambiguityinprogramorderdefinition• GivenaprograminJava
• Programorderdoesnotmeanthaty=6mustbesubsequenttox=5fromawallclockperspective.Itonlymeansthatthesequenceofactionsexecutedmustbeconsistent withthatorder
3/26/19 23
y=6x=5
12
Whatshouldbeconsistentinprogramorder• Happens-beforeconsistency
• Areadr ofavariablev isallowedtoobserveawritew tov if• r doesnothappen-beforew (i.e.,itisnotthecasethathb(r,w))– areadcannotseeawritethathappens-afterit,and
• Thereisnointerveningwritew0 tov(i.e.,nowritew0 tov suchthathb(w,w0),hb(w0,r))–thewritew isnotoverwrittenalongahappens-beforepath.
• GivenaJavaprogram
• hb(1,2)&hb(2,3)->hb(1,3),soz sees6bewrittentoy
3/26/19 24
y=6x=5z=y
123
SynchronizationOrder
• Asynchronizationorderisatotalorderoverallofthesynchronizationactionsofanexecution• Awritetoavolatilevariablev synchronizes-with allsubsequentreadsofv byanythread;• Anunlockactiononmonitorm synchronizes-with allsubsequentlockactionsonm thatwereperformedbyanythread;• …
• Ifanactionx synchronizes-with afollowingactiony,thenwehavehb(x,y)
3/26/19 25
Whatshouldbeconsistentinsynchronizationorder• Synchronizationorderconsistency• Synchronizationorderisconsistentwithprogramorder• Eachreadr ofavolatilevariablev seesthelastwritetovtocomebeforeitinthesynchronizationorder
3/26/19 26
Happens-beforememorymodelexample
3/26/19 27
x=1ready=true
if (ready)r1=x
Thread1 Thread2
12
34
synchronization-with
programorder
Initialconditions:x=0,ready=false,readyisvolatile
Finalresults: r1==1?
Decision:Allowed.Theprogramiscorrectlysynchronized
Proof:Programorder:hb(L1,L2)and hb(L3,L4)Synchronizationorder:hb(L2,L3)Transitive:hb(L1,L4)
Recall data-race definition:Two accesses x and y form adata race in an execution of aprogram if they are fromdifferent threads, they conflict,and they are not ordered byhappens-before
Correctdouble-checkedlockwithvolatile
3/26/19 28
public class Instance {private volatile static Instance instance;public static Instance getInstance() {if (instance == null) {synchronized (Instance.class) {if (instance == null) {
instance = new Instance();}
}}return instance;
}}
12345678910111213
1. mem = allocate();2. ctorSingleton(mem);3. object.instance = mem;
hb(2,3)ensuresthatL2’swritetomemcanbeseenatL3
Happens-beforedoesn’tsolveallproblems
3/26/19 29
r1=xif (r1!= 0)y=42
r2=yif (r2!= 0)x=42
Thread1 Thread2
Initialconditions:x=y=0
Finalresults: r1==r2==42?
Decision:Disallowed.Becausethevaluesareout-of-thin-air.
Inafutureaggressivesystem,Thread1couldspeculativelywritethevalue42toy.Howtoproposeamethodologytodisallowthesebehaviors?
123
456
Happens-beforedoesn’tsolveallproblems
3/26/19 30
r1=ar2=aif(r1==r2)b=2
r3=ba=r3
Thread1 Thread2
Initialconditions:a=0,b=1
Finalresults: r1==r2==r3==2?
Decision:Allowed.Acompilermaydeterminesthatr1 andr2 havethesamevalueandeliminateif r1==r2 (L3).Then,b=2(L4) canbemovedtoanearlierposition(L1)
1234
56
b=2r1=ar2=r1if (true)
r3=ba=r3
Thread1 Thread2
1234
45
What’sthedifferencebetweentwoprograms• Onedifferencebetweentheacceptableandunacceptableresultsisthatinlatterprogram,thewritethatweperform(i.e.b=2)wouldalsohaveoccurredifwehadcarriedontheexecutioninasequentiallyconsistentway.• Intheformerprogram,value42inanysequentiallyconsistentexecutionwillnotbewritten.
3/26/19 31
Well-behavedexecution
• Wedistinguishtwoprogramsbyconsideringwhetherthosewritescouldoccurinasequentiallyconsistentexecution.• Well-behavedexecution• Areadthatmustreturnthevalueofawritethatisorderedbeforeitbyhappens-before.
3/26/19 32
Disallowedexamples-datadependency
3/26/19 33
r1=xa[r1]=0r2=a[0]y=r2
r3=yx=r3
Thread1 Thread2
1234
56
Initialconditions:x=y=0;a[0]=1,a[1]=2
Finalresults: r1==r2==r3==1?
Decision:Disallowed.Becausevaluesareout-of-thin-air.
Proof:Wehavehb(L1,L2),hb(L2,L3).Toletr2==1,a[0]mustbe0.Sinceinitiallya[0]==1andhb(L2,L3),wehaver1==0ata[r1]=0(L2).r1 atL2 isthefinalvalueBecausehb(L1,L2),r1 atL2mustseethewritetor1 atr1=x (L1).
Disallowedexamples-controldependency
3/26/19 34
z=1 r1=zif (r1== 0)x=1
Thread1 Thread2
1 234
r2=xy=r2
Thread3
r3=yx=r3
Thread456
78
Initialconditions:x=y=z=0
Finalresults: r1==r2==r3==1?
Decision:Disallowed.Becausevaluesareout-of-thin-air.
Proof:Becausewehavehb(L5,L6),toletr2==1(sothaty=1),x=1 (L4)mustbeexecuted.IfL4 isexecuted,if (r1==0) (L3)mustbetrue.However,sincer1 ==1 andhb(L2,L3),L4 cannotbeexecuted.
Disallowedexamples-controldependency
3/26/19 35
r1=xif (r1== 0)x=1
Thread1123
r2=xy=r2
Thread2
r3=yx=r3
Thread345
67
Initialconditions:x=y=0
Finalresults: r1==r2==r3==1?
Decision:Disallowed.Becausevaluesareout-of-thin-air
Proof:Thesamereasonasthepreviousexample.
Causality
• Actionsthatarecommittedearliermaycauseactionsthatarecommittedlatertooccur• Thebehaviorofincorrectlysynchronizedprogramsisboundedbycausality• ThecausalityrequirementisstrongenoughtorespectthesafetyandsecuritypropertiesofJavaandweakenoughtoallowstandardcompilerandhardwareoptimizations
3/26/19 36
Justifyacorrectexecution
• Buildupcausalityconstraintstojustify executions• Ensuresthattheoccurrenceofacommittedactionanditsvaluedoesnotdependonanuncommitteddatarace
• Justificationsteps• StartingwiththeemptysetasC0• PerformasequenceofstepswherewetakeactionsfromthesetofactionsA andaddthemtoasetofcommittedactionsCi togetanewsetofcommittedactionsCi+1• Todemonstratethatthisisreasonable,foreachCi weneedtodemonstrateanexecutionE containingCi thatmeetscertainconditions
3/26/19 37
Justificationexamples-reorder
3/26/19 38
r1=xy=1
r2=yx=r2
Thread1 Thread2
Initialconditions:x=y=0
Finalresults: r1==r2==1?
Decision:Allowed,becauseofcompilertransformation.y=1(L2) isaconstantthatdoesnotaffectr1=x(L2).
12
34
y=1r1=x
r2=yx=r2
Thread1 Thread212
34
C1:y=1r2=y(0)x=r2(0)r1=x(0)
C2:y=1r2=y(1)x=r2(1)r1=x(0)
C3:y=1r2=y(1)x=r2(1)r1=x(0)
C4:y=1r2=y(1)x=r2(1)r1=x(1)
Justificationexamples-redundantelimination
3/26/19 39
r1=aif (r1==1)b=1
r2=bif(r2==1)a=1
if(r2==0)a=1
Thread1 Thread2
123
45678Initialconditions:a=b=0
Finalresults: r1==r2==1?
Decision:Allowed.Acompiler coulddeterminethatThread2alwayswrites1 toa andhoiststhewritetothebeginningofThread2.
C1:a=1r1=a(0)b=1(0)r2=b(0)
C2:a=1r1=a(1)b=1(0)r2=b(0)
C3:y=1r1=a(1)b=1(1)r2=b(0)
C4:y=1r1=a(1)b=1(1)r2=b(1)
r1=aif (r1==1)b=1
a=1r2=b
Thread1 Thread2
123
45
Justificationexamples-interthreadanalysis
3/26/19 40
r1=xr2=1+r1*r1– r1y=r2
r3=yx=r3
Thread1 Thread2
123
45
Initialconditions:x=y=0
Finalresults: r1==r2==1?
Decision:Allowed.Interthreadanalysiscoulddeterminethatx andy arealwayseither0 or1,andthusdeterminethatr2 isalways1.Oncethisdeterminationismade,thewriteof1 toy couldbemovedearlyinThread1.
r2=1y=r2r1=x
r3=yx=r3
Thread1 Thread2
123
45
C1:r2=1y=r2(0)r3=y(0)x=r3(0)r1=x(0)
C2:r2=1y=r2(1)r3=y(0)x=r3(0)r1=x(0)
C3:r2=1y=r2(1)r3=y(1)x=r3(0)r1=x(0)
C4:r2=1y=r2(1)r3=y(1)x=r3(1)r1=x(0)
C5:r2=1y=r2(1)r3=y(1)x=r3(1)r1=x(1)
Comparisonbetweenallowedexamplesanddisallowedexamples
3/26/19 41
r1=xif (r1== 0)x=1
Thread1123
r2=xy=r2
Thread2
r3=yx=r3
Thread345
67
r1=xif (r1== 0)x=1
r2=xy=r2
Thread112345
r3=yx=r3
Thread267
Initialconditions:x=y=0
Finalresults: r1==r2==r3 == 1?
Decision:Allowed.Interthreadanalysiscoulddeterminethatx isalways0or1.Sowecanreplacer2=xbyr2=1 andy=r2 byy=1.Aftermovingy=1 andr2=1 toanearlierposition,wegetr1==r2==r3.
y=1r2=1r1=xif (r1== 0)x=1
Thread1
r3=yx=r3
Thread267
12345
Comparisonbetweenallowedexamplesanddisallowedexamples
3/26/19 42
r1=xif (r1== 0)x=1
Thread1123
r2=xy=r2
Thread2
r3=yx=r3
Thread345
67
Initialconditions:a=b=0
Finalresults: r1==r2==r3 == 2?
Decision:Allowed.AlthoughtherearesomeSCexecutionsinwhichr1!=r2(L3),wecanhoistb=2 (L4)toanearlierpositionandthereisanSCexecutionsuchthatr1==r2.Fortheabovecase,there’snoSCexecutionsuchthatr1==0 (L2)istrue andr1==r2==r3==1.Thatis,ifwehoistx=1 toanearlierposition,L2mustbefalse.
r1=ar2=aif(r1==r2)b=2
r3=ba=r3
Thread1 Thread2
1234
12
123
12
Practicalissues-finalfield
• “Forspacereasons,weomitdiscussionoftwoimportantissuesintheJavamemorymodel:thetreatmentoffinalfields,andfinalization/garbagecollection.”• Java’sfinal fieldalsoallowsprogrammerstoimplementthread-safeimmutableobjectswithoutsynchronization
3/26/19 43
Ruleofthumb
• Setthefinalfieldsforanobjectinthatobject'sconstructor;anddonotwriteareferencetotheobjectbeingconstructedinaplacewhereanotherthreadcanseeitbeforetheobject'sconstructorisfinished.• Whathappensintheconstructor• Ifareadoccursafterthefieldissetintheconstructor,itseesthevaluethefinalfieldisassigned,otherwiseitseesthedefaultvalue.
3/26/19 44
Canwechangeafinalfield?
• Reflectionintroducesproblems• Thespecificationallowsaggressiveoptimizationoffinalfields.Withinathread,itispermissibletoreorderreadsofafinalfieldwiththosemodificationsofafinalfieldthatdonottakeplaceintheconstructor.
3/26/19 45
Practicalissues-finalfield
3/26/19 46
• new A().f()couldreturn-1,0,or1class A {final int x;A() { x = 1; }int f() { return d(this,this); }int d(A a1, A a2) {int i = a1.x;g(a1);int j = a2.x;return j - i;
}static void g(A a) {
// uses reflection to change a.x to 2}
}
1234567891011121314
reorder!
Practicalissues-finalfield
3/26/19 47
• new A().f()couldreturn-1,0,or1class A {final int x;A() { x = 1; }int f() { return d(this,this); }int d(A a1, A a2) {int i = a1.x;g(a1);int j = a2.x;return j - i;
}static void g(A a) {
// uses reflection to change a.x to 2}
}
1234567891011121314
return1
Practicalissues-finalfield
3/26/19 48
• new A().f()couldreturn-1,0,or1class A {final int x;A() { x = 1; }int f() { return d(this,this); }int d(A a1, A a2) {g(a1);int i = a1.x;int j = a2.x;return j - i;
}static void g(A a) {// uses reflection to change a.x to 2
}}
1234567891011121314
return0
Practicalissues-finalfield
3/26/19 49
• new A().f()couldreturn-1,0,or1class A {final int x;A() { x = 1; }int f() { return d(this,this); }int d(A a1, A a2) {int j = a2.x;g(a1);int i = a1.x;return j - i;
}static void g(A a) {// uses reflection to change a.x to 2
}}
1234567891011121314
return-1
Practicalissue-efficientsingleton
• Theinitialization-on-demandholder(designpattern)idiomisalazy-loadedsingleton.InallversionsofJava,theidiomenablesasafe,highlyconcurrentlazyinitializationwithgoodperformance.
3/26/19 50
public class SafeInstance {private SafeInstance() {}private static class LazyHolder {static final SafeInstance INSTANCE = new SafeInstance();
}public static SafeInstance getInstance() {return LazyHolder.INSTANCE;
}}
123456789
Whyinitialization-on-demandholderissafe?• Whentheclassisinitialized?• AclassorinterfacetypeTwillbeinitializedimmediatelybeforethefirstoccurrenceofanyoneofthefollowing:• AstaticfielddeclaredbyTisusedandthefieldisnotaconstantvariable• AvariableofprimitivetypeortypeString,thatisfinalandinitializedwithacompile-timeconstantexpressioniscalledaconstantvariable.
• …
3/26/19 51
Whyinitialization-on-demandholderissafe?• Whyinitializationissafe?• ForeachclassorinterfaceC,thereisauniqueinitializationlockLC.ThemappingfromC toLC islefttothediscretionoftheJavaVirtualMachineimplementation.• WecanalsoimplementsingletonbyENUMinJava.
3/26/19 52
Conclusion
• Followinghappens-beforerulesallowsustowriteadata-race-freeprogramthatiscorrectlysynchronized.• Javamemorymodelprovidesacleardefinitionofwell-behavedexecutions,preventingvaluescomeout-of-thin-airinthepresenceofdatarace.• Double-checkedlockisthread-safeforJVMlaterthanv1.5.
3/26/19 53
ReferenceBooks
• Goetz,Brian,etal.Javaconcurrencyinpractice.PearsonEducation,2006.• Gosling,James,etal.TheJavalanguagespecification.PearsonEducation,2014.• Lea,Doug."TheJSR-133cookbookforcompilerwriters."(2008).
3/26/19 54
ReferenceURLs
• Double-checkedlockinghttps://www.ibm.com/developerworks/java/library/j-dcl/index.html• Causalitytestcaseshttp://www.cs.umd.edu/~pugh/java/memoryModel/unifiedProposal/testcases.html
3/26/19 55