You are on page 1of 23

Threads

Threads 1
What is a Thread?

A Thread or Thread of execution refers to the execution of a sequential set of


instructions.

Multi Threading is the ability to run multiple threads of execution concurrently.

Why multi-thread?

What actually happens on a single processor?

Threads 2
Problems with multithreading

No one thread should disturbs the work of any other thread.

Example:

Imagine an office - workers function independently and work in parallel except


when they need to share office resources/communicate.

• Two workers can speak only if one speaks and the other listens
• A worker cannot use the copy machine until the machine is free

Multiple threads of a program are much like the workers

• For two threads to communicate - one has to talk and the other has to listen
• For a thread to use a shared resources, the resource has to be free and ready

Threads 3
Problems with multithreading
The Cooperative threading and Preemptive threading model

copier
copier
start copying
start copying
C pause copying
o P
start copying
o r
p done copying e
pause copying
e e
r m
restart copying
a start copying p
t t
pause copying
i i
start copying
v v
e done copying
e
pause copying

start copying

done copying
Threads 4
How do you make a class run in its own thread?
• extend Thread, or
• implement Runnable
Extending Thread

public MyThreadedClass extends Thread{


… //instance variables and methods of MyThreadedClass

public void run(){ //method inherited and overridden from Thread


//the run method is like method main for MyThreadedClass
//…
}

public static void main(){


MyThreadedClass mtc = new MyThreadedClass();
mtc.start(); //inherited from Thread
//Never call run - always call start
System.out.println(“main done”);
}
}
4. start() calls run()
5. new thread of execution for
2. creates object
MyThreadedClass
1. main begins 3. calls start() 5. prints message

main pausedThreads 6. main ends 5


4. main starts up
time
Extending Thread
import java.util.*; Points:
public class TimePrinter extends Thread{ • thread creation and activation
int pauseTime; • sleep()
String name;
public TimePrinter(int x, String n){
puaseTime = x;
name = n;
}
public void run(){
while (true){
try{
System.out.println(name+”:”+new Date(System.currentTimeMillis()));
Thread.sleep(pauseTime);
}catch(Exception e){
System.out.println(e);
}
}
}
public static void main(String args[]){
TimePrinter tp1 = new TimePrinter(1000, “Fast”);
TimePrinter tp2 = new TimePrinter(3000, “slow”);
tp1.start();
tp2.start();
System.out.println(“main-bye-bye”);
}
} What’s the downside of extending Thread?
How many threads do we have?
Threads 6
Implementing Runnable
import java.util.*;
public class TimePrinter implements Runnable{
int pauseTime;
String name;
public TimePrinter(int x, String n){
puaseTime = x;
name = n;
}
public void run(){
while (true){
try{
System.out.println(name+”:”+new Date(System.currentTimeMillis()));
Thread.sleep(pauseTime);
}catch(Exception e){
System.out.println(e);
}
}
}
public static void main(String args[]){
Thread t1 = new Thread(new TimePrinter(1000, “Fast”));
Thread t2 = new Thread(TimePrinter(3000, “slow”));
t1.start();
t2.start();
System.out.println(“main-bye-bye”);
}
}
Threads 7
Thread life cycle
born

start

ready

yield assigned a
processor
IO complete
done waiting running
notify
or notifyAll
doing IO
wait
sleep complete

waiting sleeping dead blocked

done sleeping when sleep


interval expires OR if
interrupted

Ref. Fig 15.1 “Life Cycle of a Thread”


Java How to Program, 3rd Ed. Deitel & Deitel

Threads 8
Synchronizing execution between two threads
Understanding the problem
Assume a simple BankAccount class.

public class BankAccount{


String holderName; makes a
float amount; direct-deposit
public Account(String n, float a){
makes a
holderName = n;
withdrawal
amount = a;
}
public void deposit(float a){
amount = amount + a;
}
public void withdraw(float a){ electronic
amount = amount - a; transfer
}
public float checkBalance(){
checks return amount;
balance }
}

Electronic pay
ATM
transaction
What would happen if these actions
could happen in parallel? Would the
Threads 9
account balance be correctly maintained?
Synchronizing execution between two threads
Solution - To “lock” methods so that only one thread can execute that method
public class BankAccount{
String holderName; paused
float amount;
and waiting
public Account(String n, float a){
their turn
holderName = n;
amount = a;
}
public synchronized void deposit(float a){
amount = amount + a;
}
public synchronized void withdraw(float a){
amount = amount - a;
}
public float checkBalance(){
return amount;
Locked
} Method
}
Notice: checkBalance() not synchronized one thread
allowed through
at a time

Threads 10
Synchronizing execution between two threads
An object with a synchronized method will only allow one thread at a time to
execute a synchronized method. Such an object is called a Monitor

If there are many synchronized methods only one synchronized method may be active
on an object at once; all other threads attempting to invoke synchronized methods
must wait.

Assume thread1 and thread2 both want to run a synchronized method


1. done running
Run synchronized method
Thread 1 2. issues a “notify” message
State
1. gets lock on Monitor
Cannot predict
2. starts running Ready who will start,
synchronized method State Thread1 or 2

Wait Hears the “notify”


Thread 2 message and enters
State the ready state
1. Enters wait state, waiting
on Thread 1 to finish

Thread 2 can only run unsynchronized methods of the Monitor while Thread 1 is
running a synchronized method.
Threads 11
The (classic) producer-consumer example
3-classes:
The “producer” produces an integer to be consumed by the “consumer”. The
produced value is held in a common shared cell.
Rules:
Producer Consumer
• Consumer may consume an integer once
integer • Consumer may not consume until the producer has produced

How do we make 2-objects share?

public class ProducerConsumerExample{


public static void main(String[] args){
SharedCell sc = new SharedCell();
Producer p = new Producer(sc);
Consumer c = new Consumer(sc);

Thread t1 = new Thread(p);


Thread t2 = new Thread(c);
t1.start();
t2.start();
}
} Threads 12
The producer-consumer example
public class SharedCell{
private int shared = -1;
public void set(int i){
System.out.println(“producer producing “+ i);
shared = i;
}
public int get(){
System.out.println(“Consumer consuming “+shared);
return shared;
}
}

public class Producer implements Runnable{


private SharedCell shared;
public Producer(SharedCell sc){shared = sc;}
public void run(){
int sum=0;
for(int count=0; count<10; count++){
//sleep for random amount
try{
Thread.sleep((int)(Math.random()*3000));
catch(InterruptedException e){
System.err.println(e.toString());
}
shared.set(count);
sum += count;
}
System.out.println(“Producer, produced “+sum);
Threads 13
}
}
The producer-consumer example
public class Consumer implements Runnable{
private SharedCell shared;
public Consumer (SharedCell sc){shared = sc;}
public void run(){
int val, sum=0;
do{
//sleep for random amount
try{
Thread.sleep((int)(Math.random()*3000));
catch(InterruptedException e){
System.err.println(e.toString());
}
val = shared.get();
sum += val;
}while(val != 9);
System.err.println(“Consumer, consumed ”+ sum);
}
}

Notice what happens when you run this!


Consumer consumes way more than the producer produces

Threads 14
The producer-consumer example
public class SharedCellSynchronizedI{
private int shared = -1;
public synchronized void set(int i){
System.out.println(“producer producing “+ i);
shared = i;
}
public synchronized int get(){
System.out.println(“Consumer consuming “+shared);
return shared;
}
}

Still does not work!

•How to prevent the consumer from consuming more than once?

•How to prevent the producer from producing more than once?

•Observe unpredictable nature of which thread will run after they


both enter the “ready” state.

Do we need to synchronize SharedCell methods?

Threads 15
The producer-consumer example
Create a boolean variable consumerHasConsumed
Initialize consumerHasConsumed to true
Producer (set()) Consumer (get())
If (consumerHasComsumed is false) If (consumerHasConsumed is true)
producer will “wait” consumer will “wait”
else else
producer will produce consumer will consume
set consumerHasConsumed to false set consumerHasConsumed to true
public class SharedCellSynchronizedII{
private int shared = -1;
boolean consumerHasConsumed

public synchronized void set(int i){ public synchronized int get(){


while (consumerHasConsumed == false){ while(consumerHasConsumed ){
//consumer has yet to consume - so wait. //producer has yet to produce - so wait
try{ try{
wait(); //give up control wait(); //give up control
}catch(InterruptedException e){
}catch(InterruptedException e){
e.printStackTrace();
e.printStackTrace(); }
} }
} System.out.println("Consumer consuming "+shared);
System.out.println("producer producing "+i); consumerHasConsumed = true;
shared = i; notify(); //signal the waiting producer
consumerHasConsumed = false; //to get ready
notify(); //signal the waiting return shared;
//consumer to get ready }
}
Threads 16
The producer-consumer example

public class ProducerConsumerFinal{


public static void main(String[] args){
SharedCell sc = new SharedCellSynchronizedII();
Producer p = new Producer(sc);
Consumer c = new Consumer(sc);

Thread t1 = new Thread(p);


Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}

Summary:
• Two independent threads work with a common object
• Both threads “own” the common object (not threaded)
• Because of method synchronization only one thread can
execute on the object at a time
• Both threads voluntarily give up owner ship by “waiting”
• Common object coordinates the common activity.

Threads 17
wait verses sleep - which to use? What’s the difference?

• A waiting thread can be activated using a notify command.

•Sleeping threads sleep the whole duration or till its interrupted. Use sleep/interrupt if
you want to control when a thread runs.

• Both sleep() and wait() give up contending for the CPU, even if the thread is in a
synchronized method.

• sleep() DOES NOT give up ownership of monitors, wait() does.


Question: What would have happened if we had used sleep() instead of wait()
in example?

• To use wait(), the current thread must own the objects monitor.
Huh?

Threads 18
Modeling a Train, track and a crossing using threads
Classes and interactions:

Train (threaded) - simply travels along a track

Track - not threaded has a crossing, and keeps track of the train position

Crossing arm (threaded) - lowers and raises the arm based on a signal from the track

The Train:

public class Train implements Runnable{


Track track;

public void run(){
while (!track.atStation()){
track.travelAMile();
sleep a while to model travel time
}
}
}
Threads 19
Modeling a Train, track and a crossing using threads

The track (not threaded):

public class Track{


int trainPosition;
int STATIONPOSITION;
int CROSSINGPOSITION;
CrossingArm ca;

public void travelAMile(){
trainPosition--;
if (trainPosition == CROSSINGPOSITION - 1)
wake up the crossing arm
else if (trainPosition == CROSSINGPOSITION + 1)
wake up the crossing arm
else if (trainPosition == STATIONPOSITION){
set variables to terminate the arm
wake up the crossing arm so it can terminate
}
}

public boolean isAtStation(){


return (trainPosition == STATIONPOSITION);
}
} Threads 20
Modeling a Train, track and a crossing using threads

public CrossingArm implements Runnable{


boolean alive = true;

public void run(){
while (alive){
sleep till I am awoken …
if (awoken){
if (alive) && (arm is up) lower arm
else if (alive) raise arm
}
}
}

public void destroyArm(){


alive = false;
}

Threads 21
Deadlocking

Happens when there are:


• at two shared resources
• two threads that both need both resources to complete a task.

What happens?
• Thread 1 gets the lock for resource 1 and waits on resource 2
• Thread 2 gets the lock for resource 2 and waits on 1
• Neither thread now can continue because the other thread has a critical lock

Classic Example:

• Dinners problem
• Imagine two people at dinner having to share a knife and fork
• Person 1 has gets the knife and person 2 the fork - now neither can eat.
(more general problem called Dinning philosophers problem…)

Threads 22
Deadlocking - what’s the solution?

Number the resources 1 ,.., n


Let each thread try to get resource 1 first.
unsuccessful
Enters wait state
successful

Gets the rest of the resources (2…n)

Why does this work?

• Because no thread will have resource i > 1 unless it has resource 1.


• If a thread has resource 1, then it is guaranteed to get resource 2…n also.

Threads 23

You might also like