Download Thread 1

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
System Programming
Practical Session 5
Synchronization, Liveness, Guarded Methods,
and Thread Timing
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. }
Liveness
A concurrent application's ability to execute in a timely manner.
Liveness problems:
• Deadlock
• Starvation
• Livelock
Deadlock
Thread 1
acquire Printer
acquire Scanner
use printer
use scanner
release Printer
release Scanner
Thread 1
Thread 2
acquire Scanner
acquire Printer
use scanner
use printer
release Scanner
release Printer
Thread 2
1. public class Deadlock {
2.
public static void main(String[] args) {
3.
final Object resource1 = “Printer";
4.
final Object resource2 = “Scanner";
5.
Thread t1 = new Thread(new Runnable() {
6.
public void run() {
7.
synchronized(resource1) {
8.
System.out.println("Thread 1: locked resource 1");
9.
try {Thread.sleep(50);} catch (InterruptedException e){}
10.
synchronized(resource2) {
11.
System.out.println("Thread 1: locked resource 2");
12.
}/* release resource2 */ }/* release resource1 */ } } );
13.
Thread t2 = new Thread(new Runnable() {
14.
public void run() {
15.
synchronized(resource2) {
16.
System.out.println("Thread 2: locked resource 2");
17.
try{Thread.sleep(50);} catch(InterruptedException e){}
18.
synchronized(resource1) {
19.
System.out.println("Thread 2: locked resource 1");
20.
}/* release resource1 */ }/* release resource2 */ } } );
21.
t1.start();
t2.start();
}
}
Resource Ordering
All threads acquire the locks in the same order.
Thread 1
acquire Printer
acquire Scanner
use printer
use scanner
release Printer
release Scanner
Thread 2
acquire Printer
acquire Scanner
use printer
use scanner
release Printer
release Scanner
Starvation
Some threads are waiting forever for resources that are used by
other threads.
Starvation
Some threads are waiting forever for resources that are used by
other threads.
Example1: A solution to the dinning philosophers problem in
which philosophers 1,3,5 never eat, and philosophers 2,4 eat
whenever they want.
3
2
4
1
5
Starvation
Example 2: Threads with priority.
Each thread has a priority: Low or High.
Low priority threads execute only if there are no high
priority threads.
High priority threads keep coming.
High
Low
Livelock
Threads are unable to make progress although they are
not blocked.
Livelock
Threads are unable to make progress although they are
not blocked.
Example: two threads trying to pass a shared corridor.
Thread protocol: if there is an obstacle, then move aside.
Livelock
Threads are unable to make progress although they are
not blocked.
Example: two threads trying to pass a shared corridor.
Thread protocol: if there is an obstacle, then move aside.
Guarded Methods
The guarded method model delays the execution of a thread
until a condition is satisfied.
A thread that is unable to proceed, waits for condition change
made by another thread.
Basic Thread Timing Example
Each thread is assigned a number from {1,2,…,k}.
In any point in time, only threads assigned a certain number
run. Other threads wait.
1
3
1
1
Basic Thread Timing Example
Each thread is assigned a number from {1,2,…,k}.
In any point in time, only threads assigned a certain number
run. Other threads wait.
1
3
3
1
1. class Checker {
2.
private int m_num;
3.
public Checker(int num) {
4.
this.m_num = num;
5.
}
6.
public synchronized void change(int num) {
7.
this.m_num = num;
8.
}
9.
public synchronized boolean check(int num){
10.
return (num == this.m_num);
11.
}
12. }
1. public class Threads01 {
2.
public static void main(String[] args) {
3.
Checker checkerObject = new Checker(0);
4.
Thread t[] = new Thread[9];
5.
for (int i = 0; i < t.length ; i++)
6.
t[i] = new Thread(new SleepThread(i/3+1, "NO. " +(i+1)+
7.
" done, was waiting for "+(i/3+1), checkerObject));
8.
for (int i = 0; i < t.length; i++)
9.
t[i].start();
try { Thread.sleep(1000);
10.
11.
checkerObject.change(1);
12.
Thread.sleep(1000);
13.
checkerObject.change(3);
14.
Thread.sleep(1000);
15.
checkerObject.change(2);
} catch (InterruptedException e) {}
16.
17.
18. }
}
Solution #1: Busy Waiting
1. class SleepThread implements Runnable {
2.
private int m_num;
3.
private String m_strToPrintWhenDone;
4.
private Checker m_checkerObject;
5.
SleepThread(int num, String strToPrintWhenDone,
Checker checkerObject) {
6.
this.m_num = num;
7.
this.m_strToPrintWhenDone = strToPrintWhenDone;
8.
this.m_checkerObject = checkerObject;
9.
}
10.
public void run() {
11.
/* busy waiting */
12.
while (!this.m_checkerObject.check(this.m_num))
13.
;
14.
System.out.println(this.m_strToPrintWhenDone);
15.
}
16. }
Solution #2: Sleep and Check
1. class SleepThread implements Runnable {
2.
private int m_num;
3.
private String m_strToPrintWhenDone;
4.
private Checker m_checkerObject;
5.
SleepThread(int num, String strToPrintWhenDone,
Checker checkerObject) {
6.
this.m_num = num;
7.
this.m_strToPrintWhenDone = strToPrintWhenDone;
8.
this.m_checkerObject = checkerObject;
9.
}
10.
public void run() {
11.
while (!this.m_checkerObject.check(this.m_num))
12.
{
13.
try {
14.
Thread.sleep(100);
15.
} catch (InterruptedException e) {}
16.
}
17.
System.out.println(this.m_strToPrintWhenDone);
18.
}
19. }
Solution #3: Wait and Notify
1. class SleepThread implements Runnable {
2.
………
3.
public void run()
4.
{
5.
this.m_checkerObject.returnWhenCheckIsTrue(m_num);
6.
System.out.println(m_strToPrintWhenDone);
7.
} }
8. class Checker {
9.
private int m_num;
10.
public Checker(int num) {
this.m_num = num;
}
11.
public synchronized void change(int num){
12.
this.m_num = num;
13.
this.notifyAll();
14.
}
15.
public synchronized void returnWhenCheckIsTrue(int num) {
16.
while (num != m_num) {
17.
try {
18.
this.wait();
19.
} catch (InterruptedException e) {}
20.
}
21. } }
Tips
• Use a while loop (and not an if condition) to check the precondition
• notify() Vs. notifyAll() - which of them should you use?
• When calling wait(), notifyAll() or notify() on an object, make sure
the calling thread holds the object's lock. Notice that if you do not hold
the object's lock you will receive an illegal monitor runtime exception .
• After performing a wait call on the object, the thread releases the
object's lock. Furthermore, before exiting the wait set of the object, the
thread must re-lock the object
• A thread that releases an object's, lock will NOT release other locks it
has
Advanced Synchronization Tools
CountDownLatch
Constructor:
•
CountDownLatch(int value)
Methods:
•
void countDown()
Decrements the latch value by 1.
•
void await()
Causes the current thread to wait until the latch
has counted down to zero.
1. import java.util.concurrent.*;
2. public class Threads {
3.
public static void main(String[] args)
4.
{
5.
CountDownLatch latchObject = new CountDownLatch (3);
6.
7.
Server s = new Server (latchObject);
8.
Client c1 = new Client (1, latchObject);
9.
Client c2 = new Client (2, latchObject);
10.
Client c3 = new Client (3, latchObject);
11.
Thread t1=new Thread(s);
12.
Thread t2=new Thread(c1);
13.
Thread t3=new Thread(c2);
14.
Thread t4=new Thread(c3);
15.
t1.start();
16.
t2.start();
17.
t3.start();
18.
t4.start();
19.
}
20. }
1. class Server implements Runnable {
2.
private CountDownLatch m_latchObject;
3.
public Server(CountDownLatch latchObject)
4.
{
5.
m_latchObject = latchObject;
6.
}
7.
public void run ()
8.
{
9.
synchronized (System.out)
10.
{
11.
System.out.println("Server initialized");
12.
}
13.
try {
14.
m_latchObject.await();
15.
} catch (InterruptedException e)
16.
{
17.
return;
18.
}
19.
System.out.println("Server finished");
20. }
21. }
1. class Client implements Runnable {
2.
private int m_id; private CountDownLatch m_latchObject;
3.
public Client(int id, CountDownLatch latchObject){
4.
m_id = id;
5.
m_latchObject = latchObject;
6.
}
7.
public void run () {
8.
synchronized (System.out) {
9.
System.out.println("Client #" + m_id + " started");
10.
}
11.
try { Thread.sleep(200); } catch (InterruptedException e) {}
12.
synchronized (System.out){
13.
System.out.println("Client #" + m_id + " doing something");
14.
}
15.
try { Thread.sleep(200); } catch (InterruptedException e) {}
16.
synchronized (System.out){
17.
System.out.println("Client #" + m_id + " finished");
18.
}
19.
m_latchObject.countDown();
20.
}
21. }
Related documents