Upload
others
View
32
Download
0
Embed Size (px)
Citation preview
ConcurrentProgrammingConcurrency:Correctlyandefficientlymanagingaccessto
sharedresourcesfrommul7plepossibly-simultaneousclients
Requirescoordina(on,par7cularlysynchroniza7ontoavoid
incorrectsimultaneousaccess:makesomebodyblocko Wanttoblockun7lanotherthreadis“doneusingwhatweneed”not“completelydoneexecu7ng”
Evencorrectconcurrentapplica7onsareusuallyhighlynon-determinis7c:howthreadsarescheduledaffectswhatopera7onsfromotherthreadstheyseewheno non-repeatabilitycomplicatestes7nganddebugging
1
ExamplesMul7plethreads:1. Processingdifferentbank-accountopera7ons
o Whatif2threadschangethesameaccountatthesame7me?
2. Usingasharedcacheofrecentfiles(e.g.,hashtable)o Whatif2threadsinsertthesamefileatthesame7me?
3. Crea7ngapipeline(thinkassemblyline)withaqueueforhandingworktonextthreadinsequence?o Whatifenqueueranddequeueradjustacirculararrayqueue
atthesame7me?
2
JavaConcurrency
Thejava.lang.Runnableinterfaceo voidrun();
Thejava.lang.Threadclasso Thread(Runnabler);o voidstart();o sta7cvoidsleep(longmillis);o voidjoin();o booleanisAlive();o sta7cThreadcurrentThread();
Atomicity Anac7onisatomicifitisindivisibleo Effec7vely,ithappensallatonceo Noeffectsoftheac7onarevisibleun7litiscompleteo Nootherac7onshaveaneffectduringtheac7on
InJava,integerincrement(i++)isnotatomic1. Loaddatafromvariable2. Incrementdataby13.Storedatatovariablei
RaceCondi7on
Aracecondi7oniswhenmul7plethreadsaccessshareddataandunexpectedresultsoccurdependingontheorderoftheirac7ons
Whythreads?Unlikeparallelism,notaboutimplemen7ngalgorithmsfasterButthreadss7llusefulfor:
Codestructureforresponsivenesso Example:RespondtoGUIeventsinonethreadwhileanother
threadisperforminganexpensivecomputa7on
Processoru(liza(on(maskI/Olatency)o If1thread“goestodisk,”havesomethingelsetodo
Failureisola(ono Convenientstructureifwanttointerleavemul7pletasksanddo
notwantanexcep7oninonetostoptheother
6
SharingresourcesItiscommoninconcurrentprogramsthat: Differentthreadsmightaccessthesameresourcesinanunpredictableorderorevenataboutthesame7me
Programcorrectnessrequiresthatsimultaneousaccessbepreventedusingsynchroniza7on
Simultaneousaccessisrareo Makestes7ngdifficulto Mustbemuchmoredisciplinedwhendesigning/implemen7nga
concurrentprogramo Willdiscusscommonidiomsknowntowork
7
Alice,BobBillandtheBankA. Alice to pay Bob $30 Bank actions A1. Does Alice have $30 ? A2. Give $30 to Bob A3. Take $30 from Alice B. Alice to pay Bill $30 Bank actions B1. Does Alice have $30 ? B2. Give $30 to Bill B3. Take $30 from Alice If Alice starts with $40, can Bob and Bill both get $30?
Alice,BobBillandtheBankA. Alice to pay Bob $30 Bank actions A1. Does Alice have $30 ? A2. Give $30 to Bob A3. Take $30 from Alice B. Alice to pay Bill $30 Bank actions B1. Does Alice have $30 ? B2. Give $30 to Bill B3. Take $30 from Alice If Alice starts with $40, can Bob and Bill both get $30?
A.1 A.2 B.1 B.2 A.3 B.3
CanonicalexampleCorrectcodeinasingle-threadedworld
10
class BankAccount { private int balance = 0; int getBalance() { return balance; } void setBalance(int x) { balance = x; } void withdraw(int amount) { int b = getBalance(); if(amount > b) throw new WithdrawTooLargeException(); setBalance(b – amount); } … // other operations like deposit, etc. }
InterleavingSuppose:
o ThreadT1callsx.withdraw(100) o ThreadT2callsy.withdraw(100)
Ifsecondcallstartsbeforefirstfinishes,wesaythecallsinterleaveo Couldhappenevenwithoneprocessorsinceathreadcanbepre-emptedatanypointfor7me-slicing
Ifxandyrefertodifferentaccounts,noproblemo “YoucookinyourkitchenwhileIcookinmine”o Butifxandyalias,possibletrouble…
11
AbadinterleavingInterleavedwithdraw(100)callsonthesameaccount
o Assumeini7albalance== 150
12
int b = getBalance(); if(amount > b) throw new …; setBalance(b – amount);
int b = getBalance(); if(amount > b) throw new …; setBalance(b – amount);
Thread1 Thread2
Time
“Lostwithdraw”–unhappybank
Incorrect“fix”Itistemp7ngandalmostalwayswrongtofixabadinterleaving
byrearrangingorrepea7ngopera7ons,suchas:
13
void withdraw(int amount) { if(amount > getBalance()) throw new WithdrawTooLargeException(); // maybe balance changed setBalance(getBalance() – amount); }
Thisfixesnothing!• Narrowstheproblembyonestatement• (Noteventhatsincethecompilercouldturnitbackintotheold
versionbecauseyoudidn’tindicateneedtosynchronize)• Andnowanega7vebalanceispossible–why?
MutualexclusionSanefix:Allowatmostonethreadtowithdrawfrom
accountAata7meo Excludeothersimultaneousopera7onsonAtoo(e.g.,deposit)
Calledmutualexclusion:Onethreadusingaresource(here:anaccount)meansanotherthreadmustwaito a.k.a.cri7calsec7ons,whichtechnicallyhaveotherrequirements
Programmermustimplementcri7calsec7ons
o “Thecompiler”hasnoideawhatinterleavingsshouldorshouldnotbeallowedinyourprogram
o youneedlanguageprimi7vestodoit!
14
Wrong!Whycan’tweimplementourownmutual-
exclusionprotocol?o It’stechnicallypossibleundercertainassump7ons,butwon’tworkinreallanguagesanyway
15
class BankAccount { private int balance = 0; private boolean busy = false; void withdraw(int amount) { while(busy) { /* “spin-wait” */ } busy = true; int b = getBalance(); if(amount > b) throw new WithdrawTooLargeException(); setBalance(b – amount); busy = false; } // deposit would spin on same boolean }
Justmovedtheproblem!
16
while(busy) { } busy = true; int b = getBalance(); if(amount > b) throw new …; setBalance(b – amount);
while(busy) { } busy = true; int b = getBalance(); if(amount > b) throw new …; setBalance(b – amount);
Thread1 Thread2
Time
“Lostwithdraw”–unhappybank
Whatweneed Weneedhelpfromthelanguage
Onebasicsolu7on:Lockso NotJavayet,thoughJava’sapproachissimilarandslightlymoreconvenient
AnADTwithopera7ons:o new:makeanewlock,ini7ally“notheld”o acquire:blocksifthislockisalreadycurrently“held”
ü Once“notheld”,makeslock“held”[allatonce!]o release:makesthislock“notheld”
ü If>=1threadsareblockedonit,exactly1willacquireit
17
Whythatworks AnADTwithopera7onsnew, acquire, release
Thelockimplementa7onensuresthatgivensimultaneousacquiresand/orreleases,acorrectthingwillhappeno Example:Twoacquires:onewill“win”andonewillblock
Howcanthisbeimplemented?o Needto“checkifheldandifnotmakeheld”“all-at-once”o UsesspecialhardwareandO/Ssupport
ü Seecomputer-architectureoropera7ng-systemscourseo Here,wetakethisasaprimi7veanduseit
18
Almost-correctpseudocode
19
class BankAccount { private int balance = 0; private Lock lk = new Lock(); … void withdraw(int amount) { lk.acquire(); // may block
int b = getBalance(); if(amount > b) throw new WithdrawTooLargeException(); setBalance(b – amount); lk.release(); } // deposit would also acquire/release lk }
Somemistakes Alockisaveryprimi7vemechanism
o S7lluptoyoutousecorrectlytoimplementcri7calsec7ons
Incorrect:Usedifferentlocksforwithdrawanddeposit o Mutualexclusionworksonlywhenusingsamelocko balancefieldisthesharedresourcebeingprotected
Poorperformance:Usesamelockforeverybankaccounto Nosimultaneousopera7onsondifferentaccounts
Incorrect:Forgettoreleasealock(blocksotherthreadsforever!)o Previousslideiswrongbecauseoftheexcep7onpossibility!
20
if(amount > b) { lk.release(); // hard to remember! throw new WithdrawTooLargeException(); }
Otheropera7ons Ifwithdrawanddepositusethesamelock,thensimultaneouscallstothesemethodsareproperlysynchronized
ButwhataboutgetBalanceandsetBalance?o Assumetheyarepublic,whichmaybereasonable
Iftheydonotacquirethesamelock,thenaracebetweensetBalanceandwithdrawcouldproduceawrongresult
Iftheydoacquirethesamelock,thenwithdrawwouldblockforeverbecauseittriestoacquirealockitalreadyhas
21
Re-entrantlockAre-entrantlock(a.k.a.recursivelock)
“Remembers”o thethread(ifany)thatcurrentlyholdsito acount
Whenthelockgoesfromnot-heldtoheld,thecountissetto0
If(coderunningin)thecurrentholdercallsacquire:o itdoesnotblocko itincrementsthecount
Onrelease:o ifthecountis>0,thecountisdecrementedo ifthecountis0,thelockbecomesnot-held
22
Re-entrantlocksworkThissimplecodeworksfineprovidedlk isareentrantlock OkaytocallsetBalancedirectly Okaytocallwithdraw(won’tblockforever)
23
int setBalance(int x) { lk.acquire(); balance = x; lk.release(); } void withdraw(int amount) { lk.acquire(); … setBalance1(b – amount); lk.release(); }
NowsomeJavaJavahasbuilt-insupportforre-entrantlocks
o Severaldifferencesfromourpseudocodeo Focusonthesynchronizedstatement
24
synchronized (expression) { statements }
1. Evaluatesexpressiontoanobject• Everyobject(butnotprimi7vetypes)“isalock”inJava
2. Acquiresthelock,blockingifnecessary• “Ifyougetpastthe{,youhavethelock”
3. Releasesthelock“atthematching}”• Evenifcontrolleavesduetothrow,return,etc.• Soimpossibletoforgettoreleasethelock
Javaversion#1(correctbutnon-idioma7c)
25
class BankAccount { private int balance = 0; private Object lk = new Object(); int getBalance() { synchronized (lk) { return balance; } } void setBalance(int x) { synchronized (lk) { balance = x; } } void withdraw(int amount) { synchronized (lk) {
int b = getBalance(); if(amount > b) throw … setBalance(b – amount); } } // deposit would also use synchronized(lk) }
ImprovingtheJava
Aswrinen,thelockisprivateo Mightseemlikeagoodideao Butalsopreventscodeinotherclassesfromwri7ngopera7onsthatsynchronizewiththeaccountopera7ons
Moreidioma7cistosynchronizeonthis… o Alsomoreconvenient:noneedtohaveanextraobject
26
Javaversion#2
27
class BankAccount { private int balance = 0; int getBalance() { synchronized (this){ return balance; } } void setBalance(int x) { synchronized (this){ balance = x; } } void withdraw(int amount) { synchronized (this) { int b = getBalance();
if(amount > b) throw … setBalance(b – amount); } } // deposit would also use synchronized(this) }
Syntac7csugar
Version#2isslightlypoorstylebecausethereisashorterwaytosaythesamething:
Pupngsynchronizedbeforeamethoddeclara7onmeanstheen7remethodbodyissurroundedby
synchronized(this){…}
Therefore,version#3(nextslide)meansexactlythesamethingasversion#2butismoreconcise
28
Javaversion#3(finalversion)
29
class BankAccount { private int balance = 0; synchronized int getBalance() { return balance; } synchronized void setBalance(int x) { balance = x; } synchronized void withdraw(int amount) { int b = getBalance();
if(amount > b) throw … setBalance(b – amount); } // deposit would also use synchronized }
MoreJavanotes Classjava.util.concurrent.locks.ReentrantLockworksmuchmorelikeourpseudocodeo Oqenusetry { … } finally { … }toavoidforgepngtoreleasethelockifthere’sanexcep7on
Alsolibraryand/orlanguagesupportforreaders/writerlocksandcondi(onvariables(futurelecture)
Javaprovidesmanyotherfeaturesanddetails.See,forexample:o JavaConcurrencyinPrac7cebyGoetzetal
30
31