31
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

Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

  • Upload
    others

  • View
    32

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

ConcurrentProgrammingConcurrency:Correctlyandefficientlymanagingaccessto

sharedresourcesfrommul7plepossibly-simultaneousclients

Requirescoordina(on,par7cularlysynchroniza7ontoavoid

incorrectsimultaneousaccess:makesomebodyblocko  Wanttoblockun7lanotherthreadis“doneusingwhatweneed”not“completelydoneexecu7ng”

Evencorrectconcurrentapplica7onsareusuallyhighlynon-determinis7c:howthreadsarescheduledaffectswhatopera7onsfromotherthreadstheyseewheno  non-repeatabilitycomplicatestes7nganddebugging

1

Page 2: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

ExamplesMul7plethreads:1.  Processingdifferentbank-accountopera7ons

o  Whatif2threadschangethesameaccountatthesame7me?

2.  Usingasharedcacheofrecentfiles(e.g.,hashtable)o  Whatif2threadsinsertthesamefileatthesame7me?

3.  Crea7ngapipeline(thinkassemblyline)withaqueueforhandingworktonextthreadinsequence?o  Whatifenqueueranddequeueradjustacirculararrayqueue

atthesame7me?

2

Page 3: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

JavaConcurrency

  Thejava.lang.Runnableinterfaceo  voidrun();

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

Page 4: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

Atomicity  Anac7onisatomicifitisindivisibleo  Effec7vely,ithappensallatonceo  Noeffectsoftheac7onarevisibleun7litiscompleteo  Nootherac7onshaveaneffectduringtheac7on

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

Page 5: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

RaceCondi7on

  Aracecondi7oniswhenmul7plethreadsaccessshareddataandunexpectedresultsoccurdependingontheorderoftheirac7ons

Page 6: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

Whythreads?Unlikeparallelism,notaboutimplemen7ngalgorithmsfasterButthreadss7llusefulfor:

  Codestructureforresponsivenesso  Example:RespondtoGUIeventsinonethreadwhileanother

threadisperforminganexpensivecomputa7on

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

  Failureisola(ono  Convenientstructureifwanttointerleavemul7pletasksanddo

notwantanexcep7oninonetostoptheother

6

Page 7: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

SharingresourcesItiscommoninconcurrentprogramsthat:  Differentthreadsmightaccessthesameresourcesinanunpredictableorderorevenataboutthesame7me

  Programcorrectnessrequiresthatsimultaneousaccessbepreventedusingsynchroniza7on

  Simultaneousaccessisrareo  Makestes7ngdifficulto  Mustbemuchmoredisciplinedwhendesigning/implemen7nga

concurrentprogramo  Willdiscusscommonidiomsknowntowork

7

Page 8: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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?

Page 9: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 10: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 11: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

InterleavingSuppose:

o  ThreadT1callsx.withdraw(100) o  ThreadT2callsy.withdraw(100)

Ifsecondcallstartsbeforefirstfinishes,wesaythecallsinterleaveo  Couldhappenevenwithoneprocessorsinceathreadcanbepre-emptedatanypointfor7me-slicing

Ifxandyrefertodifferentaccounts,noproblemo  “YoucookinyourkitchenwhileIcookinmine”o  Butifxandyalias,possibletrouble…

11

Page 12: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 13: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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?

Page 14: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

MutualexclusionSanefix:Allowatmostonethreadtowithdrawfrom

accountAata7meo  Excludeothersimultaneousopera7onsonAtoo(e.g.,deposit)

Calledmutualexclusion:Onethreadusingaresource(here:anaccount)meansanotherthreadmustwaito  a.k.a.cri7calsec7ons,whichtechnicallyhaveotherrequirements

Programmermustimplementcri7calsec7ons

o  “Thecompiler”hasnoideawhatinterleavingsshouldorshouldnotbeallowedinyourprogram

o  youneedlanguageprimi7vestodoit!

14

Page 15: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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 }

Page 16: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 17: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 18: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 19: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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 }

Page 20: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 21: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

Otheropera7ons  Ifwithdrawanddepositusethesamelock,thensimultaneouscallstothesemethodsareproperlysynchronized

  ButwhataboutgetBalanceandsetBalance?o  Assumetheyarepublic,whichmaybereasonable

  Iftheydonotacquirethesamelock,thenaracebetweensetBalanceandwithdrawcouldproduceawrongresult

  Iftheydoacquirethesamelock,thenwithdrawwouldblockforeverbecauseittriestoacquirealockitalreadyhas

21

Page 22: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 23: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 24: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 25: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 26: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

ImprovingtheJava

  Aswrinen,thelockisprivateo  Mightseemlikeagoodideao  Butalsopreventscodeinotherclassesfromwri7ngopera7onsthatsynchronizewiththeaccountopera7ons

  Moreidioma7cistosynchronizeonthis… o  Alsomoreconvenient:noneedtohaveanextraobject

26

Page 27: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

Page 28: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

Syntac7csugar

Version#2isslightlypoorstylebecausethereisashorterwaytosaythesamething:

Pupngsynchronizedbeforeamethoddeclara7onmeanstheen7remethodbodyissurroundedby

synchronized(this){…}

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

28

Page 29: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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 }

Page 30: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

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

  Alsolibraryand/orlanguagesupportforreaders/writerlocksandcondi(onvariables(futurelecture)

  Javaprovidesmanyotherfeaturesanddetails.See,forexample:o  JavaConcurrencyinPrac7cebyGoetzetal

30

Page 31: Concurrent Programming - Dipartimento di Informaticapages.di.unipi.it/ferrari/CORSI/AP/LEZIONI2017/COOP2.pdf · Concurrent Programming Concurrency: Correctly and efficiently managing

31