240 likes | 252 Views
Learn about concurrency and safety in system programming through practical sessions. Understand the dangers of multithreading and how to implement thread safety.
E N D
System Programming Practical Session 4: Concurrency / Safety
Threads Till now, no multithreading class Prog{ public static void main(String args []){ ……. func1(); func2(); }
Threads Step1. Implement the interface Runnable: interface Runnabe{ public void run(); } Step 2. option 1: Create Threads option 2: Use Executor
Step 1 Example class SimpleRunnable implements Runnable { private int m_number; public SimpleRunnable(int i) { this.m_number = i; } public void run() { for (int i = 0; i < 10; i++) { System.out.print(" " + m_number); } } }
Step 2. Option 1. example public class Threads01 { public static void main(String[] a) { SimpleRunnable r1 = new SimpleRunnable(1); Thread t1 = new Thread(r1); SimpleRunnable r2 = new SimpleRunnable(2); Thread t2 = new Thread(r2); t1.start(); t2.start(); } } Output: 1 1 2 2 2 1 2 1 2 2 1 1 1 1 2 2 2 2 1 1
Step 2. Option 2 - ExecutorService. example public class Threads01e { public static void main(String[] a) { // Create an executor: ExecutorService e = Executors.newFixedThreadPool(3); // create several runnables, and execute them. for(int i=0;i<10;i++) { SimpleRunnable r = new SimpleRunnable(i); e.execute(r); } e.shutdown(); } }
Threads can be Dangerous Example: Two teaching assistants and one electronic Announcements page. Announcments A B C Announcments A B C Y TA1 downloads page Adds msg X upload Time TA2 downloads page Adds msg Y upload
Threads can be Dangerous class Printer { Printer() {} /** * Print a numbered line of the string 's' 40 times. * @param i line number * @param s the string to concatenate */ public void printALine(int i, String s) { System.out.print(i + ") "); for (int j = 0; j < 40; j++) { System.out.print(s); } System.out.println(); } } Code Example 1: One printer and two threads
Example 1 continued class SimpleAsynchronousTask implements Runnable { Printer m_p; String m_name; SimpleAsynchronousTask(String name, Printer p) { m_p = p; m_name = name; } public void run() { for (int i = 0; i<50; i++) { m_p.printALine(i, m_name); } } }
Example 1 continued public class Threads02 { static void main(String[] a) { Printer p = new Printer(); Thread t1 = new Thread(new SimpleAsynchronousTask("a", p) ); Thread t2 = new Thread(newSimpleAsynchronousTask("b", p) ); t1.start(); // prints some lines of aaaa t2.start(); // prints some lines of bbbb } }
Example 2: Even counter class Even { private long n = 0; //@ pre-condition: n is even public long next() { n++; try {Thread.sleep(30);} catch (InterruptedException e) { } n++; return n; //@ post-condition : n is greater by two } import java.util.concurrent.*; class EvenTask implements Runnable { Even m_even; EvenTask(Even even) { m_even = even; } public void run() { for (int i = 0; i < 50; i++) { System.out.println(m_even.next()); } } } public class Threads03 { public static void main(String[] args) { ExecutorService e = Executors.newFixedThreadPool(10); Even ev = new Even(); for (int i=0; i<10; i++) { e.execute(new EvenTask(ev)); } e.shutdown(); } }
Solution (Trial) class Even { private long n = 0; //@ pre-condition: n is even public long next() throws NotEvenException { if (n%2 != 0) { throw new NotEvenException( "PRE: n is not even!"); } n++; try {Thread.sleep(30);} catch (InterruptedException e) {} n++; if (n%2 != 0) { throw new NotEvenException( "POST: n is not even!"); } return n; } //@ post-condition : n is greater in two } class EvenTask implements Runnable { Even m_even; EvenTask(Even even) { m_even = even; } public void run() { try { for (int i = 0; i < 50; i++) { System.out.println( m_even.next()); } } catch (NotEvenException e) { System.out.println("Exception in “ + Thread.currentThread().getName()); e.printStackTrace(System.out); } } } class NotEvenException extends Exception { public NotEvenException (String message){ super(message); } }
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 visible 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 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); } }
Summary • The most useful policies for using and sharing objects in a concurrent program are: • Thread-confined • Shared read-only • Shared thread-safe