synchroniza+onsynchroniza+on cs 4410, operang systems fall 2016 cornell university rachit agarwal...
TRANSCRIPT
Synchroniza+on
CS4410,Opera+ngSystems
Fall2016CornellUniversity
RachitAgarwalAnneBracy
See:Ch5&6inOSPPtextbook
TheslidesaretheproductofmanyroundsofteachingCS4410byProfessorsSirer,Bracy,Agarwal,George,andVanRenesse.
Synchroniza+on:Topic1
2
Synchroniza+onMo+va+on&Basics• RaceCondi+ons• Cri+calSec+ons• Example:TooMuchMilk• BasicHardwarePrimi+ves• BuildingaSpinLock
ThreadsShareMemory
3
Threadshave:•Privateregisters
Contextswitchingsavesandrestoresregisterswhenswitchingfromthreadtothread
•Shared“global”memoryGlobalmeansnotstackmemory
•UsuallyprivatestackPointersintostacksacrossthreadsfrownedupon
2threadsupda+ngasinglesharedvariableamount• Onethreadwantstodecrementamountby$10K• Otherthreadwantstodecrementamountby50%
Whathappenswhentwothreadsexecuteconcurrently?
Memory
TwoTheads,OneVariable
4
...amount-=10,000;
...
...amount*=0.5;
...
100,000amount
T1 T2
Itwon’tactuallyexecutelikethis:
Memory
TwoTheads,OneVariable
5
...r1=loadfromamountr1=r1–10,000storer1toamount...
...r2=loadfromamountr2=0.5*r2storer2toamount...
100,000amount
T1 T2
Itmightexecutelikethis:
Memory
TwoTheads,OneVariable
6
...r1=loadfromamountr1=r1–10,000storer1toamount...
...r2=loadfromamountr2=0.5*r2storer2toamount...
100,000amount
Everythingworks:althoughdifferent,eitherorderiscorrect
T1
T2
Oritmightexecutelikethis:
Memory
TwoTheads,OneVariable
7
...r1=loadfromamountr1=r1–10,000storer1toamount...
...r2=loadfromamount
...
r2=0.5*r2storer2toamount...
100,000amount
LostUpdate:Wrong..andverydifficulttodebug
T1
T2
RaceCondiLons
8
Allpossibleinterleavingsshouldbesafe!
=+mingdependenterrorinvolvingsharedstate•OncethreadAstarts,itneedsto“race”tofinish•Whetherracecondi+onhappensdependsonthreadschedule•Different“schedules”or“interleavings”(totalorderonmachineinstruc+ons)
RaceCondiLonsareHardtoDebug
9
•Numberofpossibleinterleavingsishuge•Someinterleavingsaregood•Someinterleavingsarebad:
•Butbadinterleavingsmayrarelyhappen!•Works100x≠noracecondi+on
•Timingdependent=smallchangescanhidebug
CaseStudy:Therac-25
Example:RaceswithQueues
10
2concurrentenqueue()opera+ons?2concurrentdequeue()opera+ons?
Whatcouldpossiblygowrong?
tail head
CriLcalSecLon
11
Codethatcanbeexecutedbyonlyonethreadata+me
GoalsSafety:1threadinacri+calsec+onat+meLiveness:allthreadseventuallymakeitintoCSifdesiredFairness:allhaveequalchancesofgemngintoCS…inprac+ce,fairnessrarelyguaranteed
...CSEnter();CriticalsectionCSExit();...
...CSEnter();CriticalsectionCSExit();...
T1 T2
TooMuchMilkProblem
12
2roommatesfridgealwaysstockedwithmilk•fridgeisempty→needtorestockit•don’twanttobuytoomuchmilk
Caveats•Onlycommunicatebyanotepadonthefridge•Notepadhascellswithnames,likevariables:outtobuymilk
TASK:Writethepseudo-codetoensurethatatmostoneroommategoestobuymilk
0
SoluLon#1:NoProtecLon
13
iffridge_empty(): buy_milk()
iffridge_empty(): buy_milk()
T1 T2
Safety:Onlyoneperson(atmost)buysmilkLiveness:Ifmilkisneeded,someoneeventuallybuysit.Fairness:Roommatesequallylikelytogotobuymilk.
Safe?Live?Fair?
SoluLon#2:addabooleanflag
14
while(outtobuymilk):do_nothing();iffridge_empty():outtobuymilk=1buy_milk() outtobuymilk=0
while(outtobuymilk):do_nothing();iffridge_empty():outtobuymilk=1buy_milk() outtobuymilk=0
T1 T2
Safety:Onlyoneperson(atmost)buysmilkLiveness:Ifmilkisneeded,someoneeventuallybuysit.Fairness:Roommatesequallylikelytogotobuymilk.Safe?Live?Fair?
outtobuymilkini+allyfalse
SoluLon#3:addtwobooleanflags!
15
blueonit=1ifnotgreenonitandfridge_empty(): buy_milk()blueonit=0
greenonit=1ifnotblueonitandfridge_empty(): buy_milk()greenonit=0
T1 T2
oneforeachroommate(ini+allyfalse)blueonit,greenonit
Safety:Onlyoneperson(atmost)buysmilkLiveness:Ifmilkisneeded,someoneeventuallybuysit.Fairness:Roommatesequallylikelytogotobuymilk.Safe?Live?Fair?
SoluLon#4:asymmetricflags!
16
blueonit=1whilegreenonit:do_nothing()iffridge_empty(): buy_milk()blueonit=0
greenonit=1ifnotblueonitandfridge_empty(): buy_milk()greenonit=0
T1 T2
‒ complicated (and this is a simple example!) ‒ hard to ascertain that it is correct ‒ asymmetric code is hard to generalize & unfair
oneforeachroommate(ini+allyfalse)blueonit,greenonit
Safe?Live?Fair?
LastSoluLon:Peterson’sSoluLon
17
blueonit=1turn=greenwhile(greenonitandturn==green):do_nothing()iffridge_empty(): buy_milk()blueonit=0
greenonit=1turn=bluewhile(blueonitandturn==blue):do_nothing()iffridge_empty(): buy_milk()greenonit=0
T1 T2
‒ complicated (and this is a simple example!) ‒ hard to ascertain that it is correct ‒ hard to generalize, inefficient
anotherflagturn{blue,green}
Safe?Live?Fair?
HardwareSoluLon
18
•Hardwareprimi+vestoprovidemutualexclusion•Typicallyreliesonamul+-cyclebusopera+onthatatomicallyreadsandupdatesamemoryloca+on
•ExampleSpecofTest-And-Set:
setsthevalueto1,returnsformervalue
ATOMICintTestAndSet(int*var){ intoldVal=*var; *var=1; returnoldVal;}
Spinlocks
19
SL_acquire(int*lock){while(test_and_set(lock)) /*donothing*/;}
SL_release(int*lock){ *lock=0;}
BuyingMilkwithSpinlock
20
Sharedspinlock:intbuyingmilk,ini+ally0
SL_acquire(&buyingmilk)iffridge_empty(): buy_milk()SL_release(&buyingmilk)
SL_acquire(&buyingmilk)iffridge_empty(): buy_milk()SL_release(&buyingmilk)
T1 T2
SpinLockIssues
21
Par+cipantsnotincri+calsec+onmustspin→was<ngCPUcycles
• Replacethe“donothing”loopwitha“yield()”?Processeswoulds+llbescheduledanddescheduled
Needbeqerprimi+ve:• allowsoneprocesstopassthrough• allotherstosleepun+ltheycanbeexecutedagain
Synchroniza+on:Topic2
22
Semaphores• Defini+on• BinarySemaphores• Coun+ngSemaphores• Implemen+ngSemaphores• ClassicSynchroniza+onProblems(w/Semaphores)
• Producer-Consumer(w/aboundedbuffer)• Readers/WritersProblems
• ClassicSemaphoreMistakes• SemaphoresConsideredHarmful
Non-nega+veintegerw/atomicincrement,decrementS=newSemaphore(init)//mustinitialize!Canonlybemodifiedby:
• P(S):decrementorblockifalready0• V(S):increment&wakeupanywai+ngthreads• Nointerfacetoreadthevalue
WhatisaSemaphore?
23
Opera+onshavethefollowingseman+cs:
[Dijkstra 1962]
P(S){while(S==0);S-=1;}
V(S){S+=1;}
Dutch 4410: P = Probeer (‘Try') and V = Verhoog ('Increment', 'Increase by one')
BinarySemaphore
24
Semaphorevalueiseither0or1• Usedformutualexclusion
(semaphoreasamoreefficientlock)• Ini+ally1inthatcase
P(S)CriticalSection()V(S)
P(S)CriticalSection()V(S)
T1 T2
SemaphoreSS.init(1)
Semacountcanbeanyinteger• Usedforsignalingorcoun+ngresources• Typically:
• onethreadperformsP()toawaitevent• anotherthreadperformsV()toalertwai+ngthreadthateventhasoccurred
CounLngSemaphores
25
PacketProcessor():x=get_packet_from_card()enqueue(packetq,x);V(packetarrived);
NetworkingThread():P(packetarrived);x=dequeue(packetq);print_contents(x);
T1 T2
Semaphorepacketarrivedpacketarrived.init(0)
StarterSemaphoreimplementaLon
26
P(Sema*s){while(TRUE){ ifs.countbigenoughbreak; } decrements.count}
V(Sema*s){increments.count
}
structSemaphore{intcount;}
Dowelikethis?
2.Busy-wai<ngisbad!Countnotbigenough?→makenoteofthread’sinterestandstopit.(haveVstartitagainwhencountbigenough)
Assumeathread“stuck”inP()willbeeventuallyinterrupted
1.SharedstateisnotprotectedThreadscanbeinterruptedatanypoint?→needalock
Producer-ConsumerProblem
27
2+threadscommunicate:somethreadsproducedatathatothersconsume
Boundedbuffer:sizeNProducerprocesswritesdatatobuffer• Writestoinandmovesrightwards• Don’twritemorethanN!Consumerprocessreadsdatafrombuffer• Readsfromoutandmovesrightwards• Don’tconsumeifthereisnodata!
Example:“pipe”(|)inUnix>catfile|sort|uniq|more
0 N-1
in out
SoluLon#1:NoProtecLon
28
//additemtobuffervoidproduce(intitem){buf[in]=item;in=(in+1)%N;}
//removeitemintconsume(){intitem=buf[out];out=(out+1)%N;returnitem;}
Problems:1.Unprotectedsharedstate(mul+pleproducers/consumers)2.Inventory:•Consumercouldconsumewhennothingisthere!•Producercouldoverwritenot-yet-consumeddata!
Shared:intbuf[N];intin,out;
SoluLon#2:AddMutexSemaphores
29
//additemtobuffervoidproduce(intitem){P(mutex_prod);
buf[in]=item;in=(in+1)%N;V(mutex_prod);
}
//removeitemintconsume(){P(mutex_cons);intitem=buf[out];out=(out+1)%N;V(mutex_cons);returnitem;}
Shared:intbuf[N];intin,out;Semaphoremutex_prod(1),mutex_cons(1);
now atomic
SoluLon#3:AddCommunicaLonSemaphores
30
voidproduce(intitem){P(nRoom);//need spaceP(mutex_prod);
buf[in]=item;in=(in+1)%N;V(mutex_prod);V(nData);//new item!
}
intconsume(){P(nData);//need itemP(mutex_cons);intitem=buf[out];out=(out+1)%N;V(mutex_cons);V(nRoom);//more space!
returnitem;}
Shared:intbuf[N];intin,out;Semaphoremutex_prod(1),mutex_cons(1);SemaphorenRoom(N),NData(0);
Readers-WritersProblem
31
Modelsaccesstoadatabase:shareddatathatsomethreadsreadandotherthreadswriteWanttoallow:•mul+pleconcurrentreaders—OR—(exclusive)•onlyasinglewriterata+me
Example:makinganairlinereserva+on• Whenyoubrowsetolookatflightschedulesthewebsiteactsasareaderonyourbehalf
• Whenyoureserveaseat,websitehastowriteintodatabasetomakethereserva+on
[Courtois+ 1971]
Readers-WritersConstraints
32
Nthreadsshare1objectinmemory• Somewrite:1writerac+veata+me• Someread:nreadersac+vesimultaneously
Insight:generalizesthecri+calsec+onconcept
Ques+ons:1.Writerac+ve&comboofreaders/writersarrive.Whoshouldgetinnext?
2.Writerwai+ng&endlessof#ofreaderscome.FairforthemtobecomeacLve?
Fornow:back-and-forthturn-taking:• Ifareaderiswai+ng,readersgetinnext• Ifawriteriswai+ng,onewritergetsinnext
Readers-WritersSoluLon
33
voidwrite(){
P(rw_lock);.../*performwrite*/...V(rw_lock);
}
intread(){P(count_mutex);rcount++;if(rcount==1)P(rw_lock);V(count_mutex);.../*performread*/...P(count_mutex);rcount--;if(rcount==0)V(rw_lock);V(count_mutex);}
Shared:intrcount;Semaphorecount_mutex(1);Semaphorerw_lock(1);
Readers-Writers:UnderstandingtheSoluLon
34
Ifthereisawriter:• Firstreaderblocksonrw_lock• Otherreadersblockonmutex
Onceareaderisac+ve,allreadersgettogothrough• Whichreadergetsinfirst?
Thelastreadertoexitsignalsawriter• Ifnowriter,thenreaderscancon+nue
Ifreadersandwriterswai+ngonrw_lock&writerexits• Whogetstogoinfirst?
Readers-Writers:AssessingtheSoluLon
35
Whenreadersac+venowritercanenter✔• Writerswait@P(rw_lock)
Whenwriterisac+venobodycanenter✔• Anyotherreaderorwriterwillwait(where?)
Back-and-forthisn’tsofair:• Anynumberofreaderscanenterinarow• Readerscan“starve”writers
Fairback-and-forthsemaphoresolu+onistricky!• Tryit!(don’tspendtoomuch+me…)
ClassicSemaphoreMistakes
36
P(S)CSP(S)
I
V(S)CSV(S)
P(S)CS
J
K
P(S)if(x)return;CSV(S)
L
Istuckon2ndP().Subsequentprocessesfreezeupon1stP().
Underminesmutex:•Jdoesn’tgetpermissionviaP()•“extra”V()sallowotherprocessesintotheCSinappropriately
NextcalltoP()willfreezeup.Confusingbecausetheotherprocesscouldbecorrectbuthangswhenyouuseadebuggertolookatitsstate!
ConditionalcodecanchangecodeflowintheCS.Causedbycode
updates(bugfixes,etc.)bysomeoneotherthanoriginalauthorofcode.
⬅typo
⬅typo
⬅omission
SemaphoresConsideredHarmful
37
“Duringsystemconcep+onittranspiredthatweusedthesemaphoresintwocompletelydifferentways.Thedifferenceissomarkedthat,lookingback,onewonderswhetheritwasreallyfairtopresentthetwowaysasusesoftheverysameprimi+ves.Ontheonehand,wehavethesemaphoresusedformutualexclusion,ontheotherhand,theprivatesemaphores.”
—Dijkstra“Thestructureofthe’THE’-Mul+programmingSystem”Communica+onsoftheACMv.11n.5May1968.
SemaphoresNOTtotherescue!
38
Semaphoresare“low-level”primi+ves.Smallerrors:• Easilybringsystemtogrindinghalt• Verydifficulttodebug
Twousagemodels:• Mutualexclusion:“real”abstrac+onisacri+calsec+on• Communica<on:threadsusesemaphorestocommunicate(e.g.,boundedbufferexample)
Simplifica<on:Provideconcurrencysupportincompiler➙EnterMonitors
Synchroniza+on:Topic3
39
Monitors&Condi<onVariables• Defini+on• Seman+cs• SimpleMonitorExample• vs.Semaphores• ClassicSynchroniza+onProblems(w/Monitors)
• BoundedBufferProducer-Consumer• Readers/WritersProblems
• ClassicSynchroniza+onMistakes(w/Monitors)
WhatisaMonitor?
40
AbstractDataTypeforhandlingsharedresources,comprising:1.SharedPrivateData
• theresource• cannotbeaccessedfromoutside
2.Proceduresthatoperateonthedata• gatewaytotheresource• canonlyactondatalocaltothemonitor
3.Synchroniza+onprimi+ves• amongthreadsthataccesstheprocedures
[Hoare 1974]
MonitorSemanLcsguaranteemutualexclusion
41
Onlyonethreadcanexecutemonitorprocedureatany+me(aka“inthemonitor”)
Monitormonitor_name{// shared variable declarationsprocedureP1(){}
procedureP2(){}..procedurePN(){}
initialization_code(){}}
Monitorstack{inttop;
voidpush(any_t*){}
any_t*pop(){}
initialization_code(){}}
intheabstract forexample:
only one operation can execute at a time
MonitorscandefineCondi+onVariables
42
Amechanismtowaitforevents3opera+onsonCondi+onVariableConditionx;•x.wait():atomically release monitor lock and relinquish
processor, sleep until woken up (or you wake up on your own)• x.signal():wake at least one process waiting on condition (if there is one). No history associated with signal. • x.broadcast():wakeallprocesseswai+ngoncondition (useful for resource manager)
You must hold the monitor lock to call these operations.
!! NOT the same thing as UNIX wait and UNIX signal !!
UsingCondiLonVariables
43
Towaitforsomecondi+on: whilenotsome_predicate(): CV.wait()
•Atomicallyreleasesthemonitorlockandyieldsprocessor
•asCV.wait()returns,lockisautoma+callyreacquired
Whenthecondi+onbecomessa+sfied: CV.broadcast(): wakesupallthreads CV.signal():wakesupatleastonethread
TypesofWaitQueues
44
Monitorshavetwokindsof“wait”queues• Entrytothemonitor:hasaqueueofthreadswai+ngtoobtainmutualexclusion&enter
• Condi<onvariables:eachcondi+onvariablehasaqueueofthreadswai+ngontheassociatedcondi+on
KidandCookThreads
45
kid_main(){
dig_in_mud();BK.kid_eat();bathe();draw_on_walls();BK.kid_eat();
facetime_Karthik();facetime_oma();BK.kid_eat();}
cook_main(){wake();shower();drive_to_work();while(not_5pm)BK.makeburger();drive_to_home();watch_got();sleep();
}
MonitorBurgerKing{Lockmlock;
intnumburgers=0;conditionhungrykid;
voidkid_eat(){mlock.acquire() while(numburgers==0) hungrykid.wait() numburgers-=1mlock.release()}
voidmakeburger(){mlock.acquire() ++numburger; hungrykid.signal();mlock.release()}}
0
Ready Running
notalways
thisexplicit
SynchronizaLon:TheBigPicture
46
Shared Objects
Synchronization Variables
Atomic Instructions
Hardware
Interrupt Disable
Bounded Buffer
Multiple Processors
Semaphores Locks
Test-and-Set
Barrier
Hardware Interrupts
Condition Variables
Concurrent Applications
LanguageSupport
47
Canbeembeddedinprogramminglanguage:• Compileraddssynchroniza+oncode,enforcedatrun+me
• Mesa/CedarfromXeroxPARC• Java:synchronized,wait,no+fy,no+fyall• C#:lock,wait(with+meouts),pulse,pulseall• Python:acquire,release,wait,no+fy,no+fyAll
Producer-Consumer
48
MonitorProducer_Consumer{charbuf[SIZE];intn=0,tail=0,head=0;conditionnot_empty,not_full;voidproduce(charch){ while(n==SIZE) wait(not_full); buf[head]=ch; head=(head+1)%SIZE; n++;notify(not_empty);}
charconsume(){ while(n==0) wait(not_empty); ch=buf[tail]; tail=(tail+1)%SIZE; n--; notify(not_full); returnch;}}
Whatifnothreadiswai+ngwhenno+fy()called?
Thensignalisanop.VerydifferentfromcallingV()onasemaphore–semaphoresrememberhowmany+mesV()wascalled!
CondiLonVariablesvs.Semaphores
49
Accesstomonitoriscontrolledbyalock.Tocallwaitorsignal,threadmustbeinmonitor(=havelock).Waitvs.P:
• SemaphoreP()blocksthreadonlyifvalue<1• waitalwaysblocks&givesupthemonitorlock
Signalvs.V:causeswai+ngthreadtowakeup• V()increments➙futurethreadsdon'twaitonP()• Nowai+ngthread➙signal=nop• Condi+onvariableshavenohistory!
Monitorseasierandsaferthansemaphores• Lockacquire/releaseareimplicit,cannotbeforgoqen• Condi+onforwhichthreadsarewai+ngexplicitlyincode
ReadersandWriters
50
MonitorReadersNWritersintwaitingWriters=0,waitingReaders=0,nReaders=0,nWriters=0;ConditioncanRead,canWrite;
voidBeginWrite()assert(nReaders==0ornWriters==0)++waitingWriterswhile(nWriters>0ornReaders>0) canWrite.wait();--waitingWritersnWriters=1;
voidEndWrite()assert(nWriters==1andnReaders==0)nWriters=0ifWaitingWriters>0 canWrite.signal();elseifwaitingReaders>0canRead.broadcast();
voidBeginRead() assert(nReaders==0ornWriters==0) ++waitingReaders while(nWriters>0orwaitingWriters>0) canRead.wait(); --waitingReaders ++nReaders
voidEndRead() assert(nReaders>0andnWriters==0) --nReaders; if(nReaders==0andwaitingWriters>0)canWrite.signal();
[slide31]
UnderstandingtheSoluLon
51
Awritercanenterif:• nootherac+vewriter
and• nowai+ngreaders
Whenawriterfinishes:checkstoseeifreaderswai+ng:Y➙letsallenterN➙ifwriterwai+ng,lets1enter
Areadercanenterif:• noac+vewriterand• nowai+ngwriters
Whenlastreaderfinishes:• itlets1writerin(ifany)
Fair?
52
Wantstobefair:• Ifawriteriswai+ng,readersqueueup• Ifareader(oranotherwriter)isac+veorwai+ng,writersqueueup
…mostlyfair,althoughonceitletsareaderin,itletsALLwai+ngreadersinallatonce,evenifsomeshowedup“a�er”otherwai+ngwriters
Hoarevs.MesaSemanLcsforMonitors
53
HoareSeman<cs:monitorlockistransferreddirectlyfromthesignalingthreadtothenewlywokenupthread
- notusuallydesirabletoforcesignalingthreadtorelinquishthemonitorlockimmediatelytoawokenupthread
- confoundsschedulingwithsynchroniza+on,penalizesthreads
MesaSeman<cs:putsawokenupthreadonthemonitorentryqueue,butdoesnotimmediatelyrunthatthread,ortransferthemonitorlock
WhichisMesa?WhichisHoare?
54wikipedia.org
ClassicMistakeswithMonitors
55
#1:NakedWaits
whilenotsome_predicate(): CV.wait()
Whatiswrongwiththis? random_fn1() CV.wait() random_fn2()
Howaboutthis?withself.lock:a=Falsewhilenota:self.cv.wait()a=True
ClassicMistakeswithMonitors
56
#2:Ifvs.While
Whatiswrongwiththis? ifnotsome_predicate(): CV.wait()
ClassicMistakeswithMonitors
57
#3:SplitPredicatesWhatiswrongwiththis?withlock:whilenotcondA:condA_cv.wait()whilenotcondB:condB_cv.wait()
Beqer:withlock:whilenotcondAornotcondB:ifnotcondA:condA_cv.wait()ifnotcondB:condB_cv.wait()
Synchroniza+on:FinalTopics
58
MappingtoRealLanguages
BarrierSynchroniza<on
AnotherClassic:BarbershopProblem
MonitorsinPython
59
classRWlock:def__init__(self):
self.lock=Lock()self.canRead=Condition(self.lock)self.canWrite=Condition(self.lock)self.nReaders=0self.nWriters=0self.nWaitingReaders=0self.nWaitingWriters=0
defend_read(self):withself.lock:self.nReaders-=1ifself.nReaders==0andself.nWaitingWriters>0:self.canWrite.notify()
signal()➙notif
y()
broadcast)➙
notifyAll()
defbegin_read(self):withself.lock: self.nWaitingReaders+=1whileself.nWriters>0orself.nWaitingWriters>0:self.canRead.wait()self.nWaitingReaders-=1self.nActiveReaders+=1
Remember that wait
• releases the lock when called
• re-acquires the lock when it returns
Wheredoestheactualreadingtakeplace?
Monitorsin“4410Python”:__init__
60
fromrvrimportMP,MPthread
classMonitorExample(MP):def__init__(self):MP.__init__(self,None)
self.lock=Lock(“monitorlock”)self.canRead=self.Lock.Condition(“canread”)self.canWrite=self.Lock.Condition(“canwrite”)self.nReaders=self.Shared(“numreaders”,0)self.nWriters=self.Shared(“numwriters”,0)self.nWaitingReaders=self.Shared(“nwaitingreaders”,0)self.nWaitingWriters=self.Shared(“nwaitingwriters”,0)
classRWlock:def__init__(self):
self.lock=Lock()self.canRead=Condition(self.lock)self.canWrite=Condition(self.lock)self.nReaders=0self.nWriters=0self.nWaitingReaders=0self.nWaitingWriters=0
Monitorsin“4410Python”:begin_read
61
defbegin_read(self):withself.lock:
self.nWaitingReaders.inc()whileself.nWriters.read()>0orself.nWaitingWriters.read()>0:
self.canRead.wait()self.nWaitingReaders.dec()self.nActiveReaders.write(self.nActiveReaders.read()+1)
defbegin_read(self):withself.lock: self.nWaitingReaders+=1whileself.nWriters>0orself.nWaitingWriters>0:self.canRead.wait()self.nWaitingReaders-=1self.nActiveReaders+=1
Whydowedothis?• helpfulfeedbackfromauto-grader• helpfulfeedbackfromdebugger
Lookinthe10-P/P2/docdirectoryfordetailsandexamplecode.
BarrierSynchronizaLon
62
• Importantsynchroniza+onprimi+veinhigh-performanceparallelprograms
• nThreadsthreadsdivvyupwork,runroundsofcomputa+onsseparatedbybarriers.
• couldfork&waitbut- threadstartupcosts- wasteofawarmcache
Createnthreads&abarrier.
Eachthreaddoesround1()barrier.checkin()
Eachthreaddoesround2()barrier.checkin()
Checkinwith1condiLonvariable
63
What’swrongwiththis?
self.allCheckedIn=Condition(self.lock)
defcheckin():withself.lock: nArrived++ ifnArrived<nThreads: whilenArrived<nThreads: allCheckedIn.wait() else: allCheckedIn.broadcast()
Checkinwith2condiLonvariables
64
• Implemen+ngbarriersisnoteasy.• Solu+onhereusesa“double-turns+le”
self.allCheckedIn=Condition(self.lock)self.allLeaving=Condition(self.lock)
defcheckin(): nArrived++ ifnArrived<nThreads://noteveryonehascheckedin
whilenArrived<nThreads: allCheckedIn.wait()//waitforeveryonetocheckinelse: nLeaving=0//thisthreadisthelasttoarrive allCheckedIn.broadcast()//telleveryonewe’reallhere!
nLeaving++ ifnLeaving<nThreads://noteveryonehasleftyet whilenLeaving<nThreads: allLeaving.wait()//waitforeveryonetoleaveelse: nArrived=0//thisthreadisthelasttoleave allLeaving.broadcast()//telleveryonewe’reouttahere!
BarbershopProblem
65
Onepossibleversion:• Abarbershopholdsuptokclients• Nbarbersworkonclients• Mclientstotalwanttheirhaircut• Eachclientwillhavetheirhaircutbythefirstbarberavailable
ImplemenLngtheBarbershop
66
(1)Iden+fythewaitsCustomers?Barbers?
(2)Createcondi+onvariablesforeach(3)Createcounterstotriggerthewai+ng(4)Createsignalsforthewaits
RulestoLiveBy
67
• Useconsistentstructure• Whenpossible,uselocksandcondi+onvariables• Alwaysacquirelockatbeginningofprocedure,releaseatend
• Alwaysholdlockwhenusingacondi+onvariable• Alwayswaitinwhileloop• Neverspininsleep()
Goreadthe12CommandmentsofSynchronizaLon
Conclusion:RaceCondiLonsareabigpain!
68
Severalwaystohandlethem• Eachhasitsownprosandcons
Programminglanguagesupportsimplifieswri+ngmul+threadedapplica+ons
• Pythoncondi+onvariables• JavaandC#supportatmostonecondi+onvariableperobject,soareslightlymorelimited
Someprogramanalysistoolsautomatechecking•makesurecodeisusingsynchroniza+oncorrectly• Hardpartistodefining“correct”
deal