Principles of Software Construction: Objects, …2019/11/05  · 17-214 2 Administrivia • Homework...

Preview:

Citation preview

1 17-214

PrinciplesofSoftwareConstruction: Objects,Design,andConcurrencyPart3:ConcurrencyIntroductiontoconcurrency:ConcurrencychallengesCharlieGarrodChrisTimperley

2 17-214

Administrivia

•  Homework5adue9a.m.tomorrow•  MidtermexamavailableonGradescope

–  RegraderequestsdueMonday,18November

•  Readingduetoday:–  JavaConcurrencyinPractice,Sections11.3and11.4

3 17-214

Winteriscomingdiscussion

4 17-214

KeyconceptsfromlastTuesday

5 17-214

Aconcurrencybugwithaneasyfix:

publicclassBankAccount{privatelongbalance;publicBankAccount(longbalance){this.balance=balance;}staticsynchronizedvoidtransferFrom(BankAccountsource,BankAccountdest,longamount){source.balance-=amount;dest.balance+=amount;}publicsynchronizedlongbalance(){returnbalance;}}

6 17-214

ConcurrencycontrolwithJava'sintrinsiclocks

•  synchronized(lock){…}–  Synchronizesentireblockonobjectlock;cannotforgettounlock–  Intrinsiclocksareexclusive:Onethreadatatimeholdsthelock–  Intrinsiclocksarereentrant:Athreadcanrepeatedlygetsamelock

•  synchronizedonaninstancemethod–  Equivalenttosynchronized(this){…}forentiremethod

•  synchronizedonastaticmethodinclassFoo–  Equivalenttosynchronized(Foo.class){…}forentiremethod

7 17-214

Atomicity

•  Anactionisatomicifitisindivisible–  Effectively,ithappensallatonce

•  Noeffectsoftheactionarevisibleuntilitiscomplete•  Nootheractionshaveaneffectduringtheaction

•  InJava,integerincrementisnotatomic

i++;

1. Load data from variable i

2. Increment data by 1

3. Store data to variable i

is actually

8 17-214

Yetanotherexample:cooperativethreadtermination

publicclassStopThread{privatestaticbooleanstopRequested;publicstaticvoidmain(String[]args)throwsException{ThreadbackgroundThread=newThread(()->{while(!stopRequested)/*Dosomething*/;});backgroundThread.start();TimeUnit.SECONDS.sleep(42);stopRequested=true;}}

9 17-214

Whatwentwrong?

•  Intheabsenceofsynchronization,thereisnoguaranteeastowhen,ifever,onethreadwillseechangesmadebyanother

•  JVMscananddoperformthisoptimization:while(!done)/*dosomething*/;

becomes:if(!done)while(true)/*dosomething*/;

Process

Thread

Copy

Thread

Copy

Memory

10 17-214

Today

•  Midtermexam2recap•  MorebasicconcurrencyinJava

–  Somechallengesofconcurrency

•  Concurrencypuzzlers•  Stillcomingsoon:

–  Higher-levelabstractionsforconcurrency–  Programstructureforconcurrency–  Frameworksforconcurrentcomputation

11 17-214

Alivenessproblem:poorperformance

publicclassBankAccount{privatelongbalance;publicBankAccount(longbalance){this.balance=balance;}staticsynchronizedvoidtransferFrom(BankAccountsource,BankAccountdest,longamount){source.balance-=amount;dest.balance+=amount;}publicsynchronizedlongbalance(){returnbalance;}}

12 17-214

Alivenessproblem:poorperformance

publicclassBankAccount{privatelongbalance;publicBankAccount(longbalance){this.balance=balance;}staticvoidtransferFrom(BankAccountsource,BankAccountdest,longamount){synchronized(BankAccount.class){source.balance-=amount;dest.balance+=amount;}}publicsynchronizedlongbalance(){returnbalance;}}

13 17-214

Aproposedfix?:locksplitting

publicclassBankAccount{privatelongbalance;publicBankAccount(longbalance){this.balance=balance;}staticvoidtransferFrom(BankAccountsource,BankAccountdest,longamount){synchronized(source){synchronized(dest){source.balance-=amount;dest.balance+=amount;}}}…}

14 17-214

Alivenessproblem:deadlock

•  Apossibleinterleavingofoperations:–  bugsThreadlocksthedaffyaccount–  daffyThreadlocksthebugsaccount–  bugsThreadwaitstolockthebugsaccount…–  daffyThreadwaitstolockthedaffyaccount…

15 17-214

Alivenessproblem:deadlock

publicclassBankAccount{privatelongbalance;publicBankAccount(longbalance){this.balance=balance;}staticvoidtransferFrom(BankAccountsource,BankAccountdest,longamount){synchronized(source){synchronized(dest){source.balance-=amount;dest.balance+=amount;}}}…}

16 17-214

Avoidingdeadlock

•  Thewaits-forgraphrepresentsdependenciesbetweenthreads–  Eachnodeinthegraphrepresentsathread–  AnedgeT1->T2representsthatthreadT1iswaitingforalockT2owns

•  Deadlockhasoccurrediffthewaits-forgraphcontainsacycle•  Onewaytoavoiddeadlock:lockingprotocolsthatavoidcycles

ab

c

d

f

e

h

g

i

17 17-214

Avoidingdeadlockbyorderinglockacquisition

publicclassBankAccount{privatelongbalance;privatefinallongid=SerialNumber.generateSerialNumber();

publicBankAccount(longbalance){this.balance=balance;}

staticvoidtransferFrom(BankAccountsource,BankAccountdest,longamount){BankAccountfirst=source.id<dest.id?source:dest;BankAccountsecond=first==source?dest:source;synchronized(first){synchronized(second){source.balance-=amount;dest.balance+=amount;}}}…

18 17-214

Anothersubtleproblem:Thelockobjectisexposed

publicclassBankAccount{privatelongbalance;privatefinallongid=SerialNumber.generateSerialNumber();

publicBankAccount(longbalance){this.balance=balance;}

staticvoidtransferFrom(BankAccountsource,BankAccountdest,longamount){BankAccountfirst=source.id<dest.id?source:dest;BankAccountsecond=first==source?dest:source;synchronized(first){synchronized(second){source.balance-=amount;dest.balance+=amount;}}}…

19 17-214

Aneasyfix:Useaprivatelock

publicclassBankAccount{privatelongbalance;privatefinallongid=SerialNumber.generateSerialNumber();privatefinalObjectlock=newObject();publicBankAccount(longbalance){this.balance=balance;}

staticvoidtransferFrom(BankAccountsource,BankAccountdest,longamount){BankAccountfirst=source.id<dest.id?source:dest;BankAccountsecond=first==source?dest:source;synchronized(first.lock){synchronized(second.lock){source.balance-=amount;dest.balance+=amount;}}}…

20 17-214

Concurrencyandinformationhiding

•  Encapsulateanobject'sstate:Easiertoimplementinvariants–  Encapsulatesynchronization:Easiertoimplementsynchronizationpolicy

21 17-214

Anaside:JavaConcurrencyinPracticeannotations

@ThreadSafepublicclassBankAccount{@GuardedBy("lock")privatelongbalance;privatefinallongid=SerialNumber.generateSerialNumber();privatefinalObjectlock=newObject();publicBankAccount(longbalance){this.balance=balance;}

staticvoidtransferFrom(BankAccountsource,BankAccountdest,longamount){BankAccountfirst=source.id<dest.id?source:dest;BankAccountsecond=first==source?dest:source;synchronized(first.lock){synchronized(second.lock){source.balance-=amount;dest.balance+=amount;}…

22 17-214

Anaside:JavaConcurrencyinPracticeannotations

•  @ThreadSafe•  @NotThreadSafe•  @GuardedBy•  @Immutable

23 17-214

Today

•  Midtermexam2recap•  MorebasicconcurrencyinJava

–  Somechallengesofconcurrency

•  Concurrencypuzzlers•  Stillcomingsoon:

–  Higher-levelabstractionsforconcurrency–  Programstructureforconcurrency–  Frameworksforconcurrentcomputation

24 17-214

Puzzler:“RacyLittleNumber”

25 17-214

Puzzler:“RacyLittleNumber”

importorg.junit.Test;importstaticorg.junit.Assert.assertEquals;publicclassLittleTest{intnumber;@Testpublicvoidtest()throwsInterruptedException{number=0;Threadt=newThread(()->{assertEquals(2,number);});number=1;t.start();number++;t.join();}}

26 17-214

Howoftendoesthistestpass?

importorg.junit.Test;importstaticorg.junit.Assert.assertEquals;publicclassLittleTest{intnumber;@Testpublicvoidtest()throwsInterruptedException{number=0;Threadt=newThread(()->{assertEquals(2,number);});number=1;t.start();number++;t.join();}}

(a)Italwaysfails(b)Itsometimespasses(c)Italwayspasses(d)Italwayshangs

27 17-214

Howoftendoesthistestpass?

(a)Italwaysfails(b)Itsometimespasses(c)Italwayspasses–butittellsusnothing(d)ItalwayshangsJUnitdoesn’tseeassertionfailuresinotherthreads

28 17-214

Anotherlook

importorg.junit.*;importstaticorg.junit.Assert.*;publicclassLittleTest{intnumber;@Testpublicvoidtest()throwsInterruptedException{number=0;Threadt=newThread(()->{assertEquals(2,number);//JUnitneverseestheexception!});number=1;t.start();number++;t.join();}}

29 17-214

Howdoyoufixit?(1)

//KeeptrackofassertionfailuresduringtestvolatileExceptionexception;volatileErrorerror;//Triggerstestcasefailureifanythreadassertsfailed@AfterpublicvoidtearDown()throwsException{if(error!=null)throwerror;if(exception!=null)throwexception;}

30 17-214

Howdoyoufixit?(2)

Threadt=newThread(()->{try{assertEquals(2,number);}catch(Errore){error=e;}catch(Exceptione){exception=e;}});*YMMV(It’saracecondition)

Nowitsometimespasses*

31 17-214

Themoral

•  JUnitdoesnotwell-supportconcurrenttests–  Youmightgetafalsesenseofsecurity

•  Concurrentclientsbeware…

32 17-214

Puzzler:“PingPong”

publicclassPingPong{publicstaticsynchronizedvoidmain(String[]a){Threadt=newThread(()->pong());t.run();System.out.print("Ping");}privatestaticsynchronizedvoidpong(){System.out.print("Pong");}}

33 17-214

Whatdoesitprint?

publicclassPingPong{publicstaticsynchronizedvoidmain(String[]a){Threadt=newThread(()->pong());t.run();System.out.print("Ping");}privatestaticsynchronizedvoidpong(){System.out.print("Pong");}}

(a)PingPong(b)PongPing(c)Itvaries

34 17-214

Whatdoesitprint?

(a)PingPong(b)PongPing(c)ItvariesNotamultithreadedprogram!

35 17-214

Anotherlook

publicclassPingPong{publicstaticsynchronizedvoidmain(String[]a){Threadt=newThread(()->pong());t.run();//Aneasytypo!System.out.print("Ping");}privatestaticsynchronizedvoidpong(){System.out.print("Pong");}}

36 17-214

Howdoyoufixit?

publicclassPingPong{publicstaticsynchronizedvoidmain(String[]a){Threadt=newThread(()->pong());t.start();System.out.print("Ping");}privatestaticsynchronizedvoidpong(){System.out.print("Pong");}}

NowprintsPingPong

37 17-214

Themoral

•  InvokeThread.start,notThread.run•  java.lang.ThreadshouldnothaveimplementedRunnable

38 17-214

Summary

•  Concurrentprogrammingcanbehardtogetright–  Easytointroducebugseveninsimpleexamples

•  Comingsoon:–  Higher-levelabstractionsforconcurrency–  Programstructureforconcurrency–  Frameworksforconcurrentcomputation

Recommended