Tirgul 3 slides

Download Report

Transcript Tirgul 3 slides

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.
1. class Foo{
2.
public static double
NUMBER = 33.3 ;}
3. class ClassA {
4. public long i ;
5. public Vector v ;
6. public ClassA (){/*…*/}
7. public void doSomething(
long x, List lst){
8.
long localVar = 0 ;
9.
Object o ;
10. o = this.v.elementAt(2);
// 1
11. localVar += 2;
// 2
12.
this.i += 2;
// 3
13. x
+= 2;
// 4
14. lst.elementAt(2);
// 5
15.
Foo.NUMBER = 4;
// 6
16.
localVar = Foo.NUMBER; // 7
1. class TaskA
implements Runnable {
2.
private ClassA a ;
3.
private List lst ;
4.
public long r ;
5. //… some code ….
6.
public void run(){
7.
8.
this.r = 2; // 8
this.a.doSomething(
9, lst); // 9
8.
9. }
}
10. class Main {
11. public static void main(
String[] args){
13. ClassA o1 = new ClassA();
14.
15.
Thread t1 =
new Thread(new TaskA(o1));
t1.start();
16.
//…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.
1. public class ThreadConfinedExample
2. {
3.
//ThreadConfined
4.
public Car createCar() {
5.
Engine e = new FuelEngine();
6.
List<Door> doors = new LinkedList<Door>();
7.
doors.add(new FrontDoor());
8.
doors.add(new FrontDoor());
9.
doors.add(new BackDoor());
10.
doors.add(new BackDoor());
11.
Radio r = new AMFMRadio();
12.
13.
Car c = new Car(e, doors, r);
14.
15.
return c;
16.
}
17.}
1. public class ThreadNotConfinedExample
2. {
3.
//NotThreadConfined
4.
5.
6.
7
8.
9.
10.
11.
public Car createCar(Engine e){
List<Door> doors = new LinkedList<Door>;
doors.add(new FrontDoor());
doors.add(new FrontDoor());
doors.add(new BackDoor());
doors.add(new BackDoor());
Radio r = new AMFMRadio());
12.
13.
Car c = new Car(e, doors, r);
14.
15.
16.}
return c ;
}
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:
1. All of its fields are final
2. The class is declared final
3. The this reference is not allowed to escape during
construction
4. 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
public final class ThreeStooges {
private final Set<String> stooges =
new HashSet<String>();
public ThreeStooges() {
stooges.add("Moe");
stooges.add("Larry");
stooges.add("Curly");
}
public boolean isStooge(String name) {
return stooges.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.
private long n = 0;
3.
public long next(){
4.
n++;
5.
n++;
6.
return n;
7.
8. }
}
Synchronization
1. Class Even{
2.
private long n = 0;
3.
public synchronized long next(){
4.
n++;
5.
n++;
6.
return n;
7.
8. }
}
Synchronizing a block
1. public int foo() {
2.
// do something safe
3.
synchronized(this) {
4.
// do something
5.
return 9;
}
6.
7.
}
Solution to safety problem
Printer Example (from practical session 1)
1. class Printer {
2.
Printer() {}
3.
/**
4.
* @param i line number
5.
* @param s the string to concatenate 40 times
6.
*/
7.
public synchronized void printALine(int i, String s) {
8.
System.out.print(i + ") ");
9.
for (int j = 0; j < 40; j++) {
10.
System.out.print(s);
11.
}
12.
System.out.println();
13. }
14.}
1. public class GoodSynchronization{
2.
public static void main(String[] a) {
3.
Printer p = new Printer();
4.
Thread t1 = new Thread( new SimpleAsynchronousTask("a", p) );
5.
Thread t2 = new Thread( new SimpleAsynchronousTask("b", p) );
6.
t1.start(); // prints some lines of aaaa
7.
t2.start(); // prints some lines of bbbb
8. } }
9. class SimpleAsynchronousTask implements Runnable {
10.
Printer m_p;
11.
String m_name;
12.
public SimpleAsynchronousTask(String name, Printer p) {
13.
m_p = p;
14.
m_name = name;
15.
}
16.
public void run() {
17.
for (int i = 0; i<50; i++) {
18.
m_p.printALine(i, m_name);
19.
}
20. } }
Wrong solution #1
1. public class BadSynchronization2
2.
public static void main(String[] a) {
3.
Printer p1 = new Printer();
4.
Printer p2 = new Printer();
5.
6.
7.
8.
9.
Thread t1 = new Thread( new SimpleAsynchronousTask("a", p1) );
Thread t2 = new Thread( new SimpleAsynchronousTask("b", p2) );
t1.start(); // prints some lines of aaaa
t2.start(); // prints some lines of bbbb
10.
}
11. }
12.
13. class SimpleAsynchronousTask implements Runnable {
14. .....the same like GoodSynchronization.java
15. class Printer {
16. .....the same like GoodSynchronization.java
17. }
Wrong solution #2 (no printer object)
1. class BadSynchronization {
2.
public static void main(String[] a) {
3.
Thread t1 = new Thread( new SimpleAsynchronousTask("a") );
4.
Thread t2 = new Thread( new SimpleAsynchronousTask("b") );
5.
t1.start(); // prints some lines of aaaa
6.
t2.start(); // prints some lines of bbbb
7.
}
8. }
9.
10. class SimpleAsynchronousTask implements Runnable {
11. .....the same like GoodSynchronization.java
12.
public synchronized void printALine(int i, String s) {
13.
System.out.print(i + ") ");
14.
for (int j = 0; j < 40; j++) System.out.print(s);
15.
System.out.println();
16.
}
17. }
Summary
The most useful policies for using and sharing objects in a concurrent
program are:
• Thread-confined
• Shared read-only
• Shared thread-safe