210 likes | 321 Views
System Programming. Practical Session 4: Concurrency / Safety. Safety. Running several threads in parallel is not safe. Unpredictable results on shared resources. Design aproaches towards avoiding safety problems Thread confinement Immutability Locking / Synchronization.
E N D
System Programming Practical Session 4: Concurrency / Safety
Safety • Running several threads in parallel is not safe. • Unpredictable results on shared resources. • Design aproaches towards avoiding safety problems • Thread confinement • Immutability • Locking / Synchronization
Shared Resources Shared resource - A resource that is visible to several threads. Objects that may be visisble to several threads - Are not safe. Objectst that cannot be shared (local function variables) - Are safe.
classFoo{ • publicstaticdouble • NUMBER=33.3;} • classClassA{ • publiclongi; • publicVectorv; • publicClassA (){/*…*/} • publicvoiddoSomething( longx,Listlst){ • longlocalVar=0; • Objecto; • o=this.v.elementAt(2); //1 • localVar+=2;//2 • this.i+=2;//3 • x+=2;//4 • lst.elementAt(2);//5 • Foo.NUMBER=4;//6 • localVar=Foo.NUMBER;//7 • } } • classTaskAimplementsRunnable{ • privateClassAa; • privateListlst; • publiclongr; • //… some code …. • publicvoidrun(){ • this.r=2;//8 • this.a.doSomething( • 9,lst);//9 • 8. } • 9. } • 10. classMain{ • 11. publicstaticvoidmain( String[]args){ • 13.ClassAo1=newClassA(); • Threadt1= • newThread(newTaskA(o1)); • 15. t1.start(); • //…some code…. } }
Thread Confinement A resource that is used exclusively by a one single thread is confined to the thread. If all the resources of a method are confined, then it is safe.
publicclassThreadConfinedExample • { • //ThreadConfined • publicCarcreateCar(){ • Enginee=newFuelEngine(); • List<Door>doors=newLinkedList<Door>(); • doors.add(newFrontDoor()); • doors.add(newFrontDoor()); • doors.add(newBackDoor()); • doors.add(newBackDoor()); • Radior=newAMFMRadio(); • Carc=newCar(e,doors,r); • returnc; • } • }
publicclassThreadNotConfinedExample • { • //NotThreadConfined • publicCarcreateCar(Enginee){ • 5.List<Door>doors=newLinkedList<Door>; • 6. doors.add(newFrontDoor()); • 7 doors.add(newFrontDoor()); • 8. doors.add(newBackDoor()); • 9.doors.add(newBackDoor()); • Radior=newAMFMRadio()); • Carc=newCar(e,doors,r); • returnc; • } • }
Immutability An immutable object’s state cannot be changed after construction. • Examples: • String • Integer
Immutability An object is immutable if • All primitive fields are final. • All other fields are references to immutable objects. • The object has been safely published: • Reference to this hasn't escaped during construction. • No thread has accessed the object before the construction completed.
‘this’ escape example Public class ClassA{ ………….. public void setB(ClassB objB) { … } ……… } Public class ClassB{ …………… public ClassB(ClassA objA){ //constructor …………… objA.setB(this); } …………… }
Immutability An object with references to mutable objects can still be immutable! A class will be immutable if all of the following are true: • All of its fields are final • The class is declared final • The this reference is not allowed to escape during construction • Any fields that contain references to mutable objects, such as arrays, collections, or mutable classes: • Are private • Are never returned or otherwise exposed to callers • Are the only reference to the objects that they reference • Do not change the state of the referenced objects after construction
publicfinalclassThreeStooges{ privatefinalSet<String>stooges= newHashSet<String>(); publicThreeStooges(){ stooges.add("Moe"); stooges.add("Larry"); stooges.add("Curly"); } publicbooleanisStooge(Stringname){ returnstooges.contains(name); } }
Synchronization A mechanism allowing safely accessing shared resources. A thread accessing a synchronized method locks the object. The object cannot be accessed by other threads while it is locked.
Synchronization 1. Class Even{ 2. privatelong n = 0; 3. publiclongnext(){ 4. n++; 5. n++; 6.returnn; 7. } 8. }
Synchronization 1. Class Even{ 2. privatelong n = 0; 3. publicsynchronizedlongnext(){ 4. n++; 5. n++; 6.returnn; 7. } 8. }
Synchronizing a block • publicintfoo(){ • //dosomething safe • synchronized(this){ • //do something • return9; • } • }
Solution to safety problem Printer Example (from practical session 1) • classPrinter{ • Printer(){} • /** • *@paramilinenumber • *@paramsthestringtoconcatenate 40 times • */ • publicsynchronizedvoidprintALine(inti,Strings){ • System.out.print(i+")"); • for(intj=0;j<40;j++){ • System.out.print(s); • } • System.out.println(); • } • }
publicclassGoodSynchronization{ • publicstaticvoidmain(String[]a){ • Printerp=newPrinter(); • Threadt1=newThread(newSimpleAsynchronousTask("a",p)); • Threadt2=newThread(newSimpleAsynchronousTask("b",p)); • t1.start();//printssomelinesofaaaa • t2.start();//printssomelinesofbbbb • } } • classSimpleAsynchronousTaskimplementsRunnable{ • Printerm_p; • Stringm_name; • publicSimpleAsynchronousTask(Stringname,Printerp){ • m_p=p; • m_name=name; • } • publicvoidrun(){ • for(inti=0;i<50;i++){ • m_p.printALine(i,m_name); • } • } }
Wrong solution #1 • publicclassBadSynchronization2 • publicstaticvoidmain(String[]a){ • Printerp1=newPrinter(); • Printerp2=newPrinter(); • Threadt1=newThread(newSimpleAsynchronousTask("a",p1)); • Threadt2=newThread(newSimpleAsynchronousTask("b",p2)); • t1.start();//printssomelinesofaaaa • t2.start();//printssomelinesofbbbb • } • } • classSimpleAsynchronousTaskimplementsRunnable{ • .....thesamelikeGoodSynchronization.java • classPrinter{ • .....thesamelikeGoodSynchronization.java • }
Wrong solution #2 (no printer object) • classBadSynchronization{ • publicstaticvoidmain(String[]a){ • Threadt1=newThread(newSimpleAsynchronousTask("a")); • Threadt2=newThread(newSimpleAsynchronousTask("b")); • t1.start();//printssomelinesofaaaa • t2.start();//printssomelinesofbbbb • } • } • classSimpleAsynchronousTaskimplementsRunnable{ • .....thesamelikeGoodSynchronization.java • publicsynchronizedvoidprintALine(inti,Strings){ • System.out.print(i+")"); • for(intj=0;j<40;j++)System.out.print(s); • System.out.println(); • } • }
Summary • The most useful policies for using and sharing objects in a concurrent program are: • Thread-confined • Shared read-only • Shared thread-safe