16
13/11/15 1 Concurrent Programming Concurrency: Correctly and efficiently managing access to shared resources from mul7ple possibly-simultaneous clients Requires coordina(on, par7cularly synchroniza7on to avoid incorrect simultaneous access: make somebody block o Want to block un7l another thread is “done using what we need” not “completely done execu7ng” Even correct concurrent applica7ons are usually highly non-determinis7c: how threads are scheduled affects what opera7ons from other threads they see when o non-repeatability complicates tes7ng and debugging 1 Examples Mul7ple threads: 1. Processing different bank-account opera7ons o What if 2 threads change the same account at the same 7me? 2. Using a shared cache of recent files (e.g., hashtable) o What if 2 threads insert the same file at the same 7me? 3. Crea7ng a pipeline (think assembly line) with a queue for handing work to next thread in sequence? o What if enqueuer and dequeuer adjust a circular array queue at the same 7me? 2

Concurrent Programming - unipi.itpages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2016/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing access to shared

Embed Size (px)

Citation preview

13/11/15

1

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

13/11/15

2

JavaConcurrency

  Thejava.lang.Runnableinterfaceo  voidrun();  Thejava.lang.Threadclasso  Thread(Runnabler);o  voidstart();o  sta7cvoidsleep(longmillis);o  voidjoin();o  booleanisAlive();o  sta7cThreadcurrentThread();  SeeIncrementTest.java

Atomicity  Anac7onisatomicifitisindivisibleo  Effec7vely,ithappensallatonceo  Noeffectsoftheac7onarevisibleun7litiscompleteo  Nootherac7onshaveaneffectduringtheac7on

  InJava,integerincrement(i++)isnotatomic1.  Loaddatafromvariable2.  Incrementdataby13.Storedatatovariablei

13/11/15

3

RaceCondi7on

  Aracecondi7oniswhenmul7plethreadsaccessshareddataandunexpectedresultsoccurdependingontheorderoftheirac7ons

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?

13/11/15

4

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

Whythreads?Unlikeparallelism,notaboutimplemen7ngalgorithmsfasterButthreadss7llusefulfor:

  Codestructureforresponsivenesso  Example:RespondtoGUIeventsinonethreadwhileanother

threadisperforminganexpensivecomputa7on

  Processoru(liza(on(maskI/Olatency)o  If1thread“goestodisk,”havesomethingelsetodo

  Failureisola(ono  Convenientstructureifwanttointerleavemul7pletasksanddo

notwantanexcep7oninonetostoptheother

8

13/11/15

5

SharingresourcesItiscommoninconcurrentprogramsthat:  Differentthreadsmightaccessthesameresourcesinanunpredictableorderorevenataboutthesame7me

  Programcorrectnessrequiresthatsimultaneousaccessbepreventedusingsynchroniza7on

  Simultaneousaccessisrareo  Makestes7ngdifficulto  Mustbemuchmoredisciplinedwhendesigning/implemen7nga

concurrentprogramo  Willdiscusscommonidiomsknowntowork

9

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. }

13/11/15

6

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

13/11/15

7

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  Buyyouneedlanguageprimi7vestodoit!

14

13/11/15

8

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

13/11/15

9

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

13/11/15

10

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(); }

13/11/15

11

Otheropera7ons  Ifwithdrawanddepositusethesamelock,thensimultaneouscallstothesemethodsareproperlysynchronized

  ButwhataboutgetBalanceandsetBalance?o  Assumetheyarepublic,whichmaybereasonable

  Iftheydonotacquirethesamelock,thenaracebetweensetBalanceandwithdrawcouldproduceawrongresult

  Iftheydoacquirethesamelock,thenwithdrawwouldblockforeverbecauseittriestoacquirealockitalreadyhas

21

Re-acquiringlocks?  Can’tletoutsideworldcallsetBalance1

  Can’thavewithdrawcallsetBalance2

  Alternately,wecanmodifythemeaningoftheLockADTtosupportre-entrantlocks

22

int setBalance1(int x) { balance = x; } int setBalance2(int x) { lk.acquire(); balance = x; lk.release(); } void withdraw(int amount) { lk.acquire(); … setBalance1(b – amount); lk.release(); }

13/11/15

12

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

23

Re-entrantlocksworkThissimplecodeworksfineprovidedlk isareentrantlock  OkaytocallsetBalancedirectly  Okaytocallwithdraw(won’tblockforever)

24

int setBalance(int x) { lk.acquire(); balance = x; lk.release(); } void withdraw(int amount) { lk.acquire(); … setBalance1(b – amount); lk.release(); }

13/11/15

13

NowsomeJavaJavahasbuilt-insupportforre-entrantlocks

o  Severaldifferencesfromourpseudocodeo  Focusonthesynchronizedstatement

25

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)

26

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) }

13/11/15

14

ImprovingtheJava

  Aswrinen,thelockisprivateo  Mightseemlikeagoodideao  Butalsopreventscodeinotherclassesfromwri7ngopera7onsthatsynchronizewiththeaccountopera7ons

  Moreidioma7cistosynchronizeonthis… o  Alsomoreconvenient:noneedtohaveanextraobject

27

Javaversion#2

28

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) }

13/11/15

15

Syntac7csugar

Version#2isslightlypoorstylebecausethereisashorterwaytosaythesamething:

Pupngsynchronizedbeforeamethoddeclara7onmeanstheen7remethodbodyissurroundedby

synchronized(this){…}

Therefore,version#3(nextslide)meansexactlythesamethingasversion#2butismoreconcise

29

Javaversion#3(finalversion)

30

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 }

13/11/15

16

MoreJavanotes  Classjava.util.concurrent.locks.ReentrantLockworksmuchmorelikeourpseudocodeo  Oqenusetry { … } finally { … }toavoidforgepngtoreleasethelockifthere’sanexcep7on

  Alsolibraryand/orlanguagesupportforreaders/writerlocksandcondi(onvariables(futurelecture)

  Javaprovidesmanyotherfeaturesanddetails.See,forexample:o  JavaConcurrencyinPrac7cebyGoetzetal

31

32