Chapter 3 Multithreading
Chapter 3 Multithreading
Chapter Three
Multithreading
MultithreadingProgramming
Programming
2
Thread
• Thread: single sequential flow of control within a
program
• Single-threaded program can handle one task at
any time
• Multitasking allows single processor to run
several concurrent threads
• Most modern operating systems support
multitasking
3
Liang, Introduction to Java Programming, Seventh Edition, (c) 2009 Pearson Education, Inc. All
rights reserved. 0136012671
4
Advantages of Multithreading
• Reactive systems – constantly monitoring
• More responsive to user input – GUI application can
interrupt a time-consuming task
• Server can handle multiple clients simultaneously
• Can take advantage of parallel processing
• Different processes do not share memory space.
• A thread can execute concurrently with other
threads within a single process
• All threads managed by the JVM share memory
space and can communicate with each other
5
Threads Concept
Multiple
threads on
multiple
CPUs
Multiple
threads sharing
a single CPU
6
Threads in Java
Creating threads in Java:
▫ Extend java.lang.Thread class
run() method must be overridden (similar to main method
of sequential program)
run() is called when execution of the thread begins
A thread terminates when run() returns
start() method invokes run()
Calling run() does not create a new thread
▫ Implement java.lang.Runnable interface
If already inheriting another class (i.e., JApplet)
Single method: public void run()
Thread class implements Runnable.
7
Thread States
8
Thread termination
• A thread becomes Not Runnable when one of
these events occurs:
▫ Its sleep method is invoked.
▫ The thread calls the wait method to wait for a
specific condition to be satisfied.
▫ The thread is blocking on I/O.
9
java.lang.Thread
+ Thread() Creates a default thread.
+ Thread(task: Runnable) Creates a thread for a specified task.
+ start(): void Starts the thread that causes the run() method to be invoked by the JVM.
+ isAlive(): boolean Tests whether the thread is currently running.
+ setPriority(p: int): void Sets priority p (ranging from 1 to 10) for this thread.
+ join(): void Waits for this thread to finish.
+ sleep(millis: long): void Puts the runnable object to sleep for a specified time in milliseconds.
+ yield(): void Causes this thread to temporarily pause and allow o ther threads to execute.
+ interrupt(): void Interrupts this thread.
12
Thread States
A thread can be in one of five states: New, Ready, Running,
Blocked, or Finished.
yield(), or Running
time out run() returns
Thread created
start()
New Ready run() join() Finished
sleep()
interrupt()
Target wait()
finished
Thread Priority
• Each thread is assigned a default priority of
Thread.NORM_PRIORITY (constant of 5)
• You can reset the priority using setPriority(int
priority).
• Some constants for priorities include
Thread.MIN_PRIORITY
Thread.MAX_PRIORITY
Thread.NORM_PRIORITY
• By default, a thread has the priority level of the thread
that created it
20
Thread Scheduling
• An operating system’s thread scheduler
determines which thread runs next.
• Most operating systems use timeslicing for
threads of equal priority.
• Preemptive scheduling: when a thread of higher
priority enters the running state, it preempts the
current thread.
• Starvation: Higher-priority threads can postpone
(possible forever) the execution of lower-priority
threads.
21
Thread Pools
• You learned how to create a thread to run a task like this:
Yield b = new Yield();
Thread t1 = new Thread(b);
t1.start();
or
Thread b = new Yield();
new Thread(b).start();
• This approach is convenient for a single task execution.
• But it is not efficient for a large number of tasks, because you
have to create a thread for each task
• Starting a new thread for each task could limit throughput and
cause poor performance.
• A thread pool is ideal to manage the number of tasks
executing concurrently.
• Java provides the Executor interface for executing tasks in a thread pool
and the ExecutorService interface for managing and controlling tasks.
22
Thread Pools…
• Executor interface for executing Runnable objects in a
thread Pool
• ExecutorService is subinterface of Executor
«interface»
java.util.concurrent.Executor
+execute(Runnable o bject): void
Thread Synchronization
• When multiple threads share an object and that object is
modified by one or more of the threads, indeterminate
results may occur. (A shared resource may be corrupted if it
is accessed simultaneously by multiple threads.)
• If one thread is in the process of updating a shared object and
another thread also tries to update it, it is unclear which
thread’s update takes effect.
• This can be solved by giving only one thread at a time
exclusive access to code that manipulates the shared object.
• Thread synchronization coordinates access to shared data
by multiple concurrent threads.
25
Thread Synchronization…
Example: two unsynchronized threads accessing the same bank
account may cause conflict.
AccountWithoutSync
Run
27
Synchronizing Object Access
• To solve problems such as the one just seen, use a lock object
• Lock object: used to control threads that manipulate shared
resources
• In Java: Lock interface and several classes that implement it
• a lock object is added to a class whose methods access shared
resources, like this:
/** This program runs threads that deposit and withdraw money from the same
bank account.*/
public class BankAccountThreadRunner {
public static void main(String[] args) {
BankAccount account = new BankAccount();
final double AMOUNT = 100;
final int REPETITIONS = 100;
final int THREADS = 100;
for (int i = 1; i <= THREADS; i++){
DepositRunnable d = new DepositRunnable(
account, AMOUNT, REPETITIONS);
WithdrawRunnable w = new WithdrawRunnable(
account, AMOUNT, REPETITIONS);
Thread dt = new Thread(d);
Thread wt = new Thread(w);
dt.start();
wt.start();
}
}
}
35
BankAccount.java
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/** A bank account has a balance that can be changed by
deposits and withdrawals.*/
public class BankAccount {
private double balance;
private Lock balanceChangeLock;
private Condition sufficientFundsCondition;
public BankAccount(){
balance = 0;
balanceChangeLock = new ReentrantLock();
sufficientFundsCondition =
balanceChangeLock.newCondition();
}
36
public void deposit(double amount){
balanceChangeLock.lock();
try {
System.out.print("Depositing " + amount);
double newBalance = balance + amount;
System.out.println(", new balance is "+newBalance);
balance = newBalance;
sufficientFundsCondition.signalAll();
}
finally {
balanceChangeLock.unlock();
}
}
37
public void withdraw(double amount)throws
InterruptedException {
balanceChangeLock.lock();
try {
while (balance < amount)
sufficientFundsCondition.await();
System.out.print("Withdrawing " + amount);
double newBalance = balance - amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
}
finally {
balanceChangeLock.unlock();
}
}
public double getBalance() {
return balance;
}
}
38
• Program Run:
• Depositing 100.0, new balance is 100.0
• Withdrawing 100.0, new balance is 0.0
• Depositing 100.0, new balance is 100.0
• Depositing 100.0, new balance is 200.0
...
• Withdrawing 100.0, new balance is 100.0
• Depositing 100.0, new balance is 200.0
• Withdrawing 100.0, new balance is 100.0
• Withdrawing 100.0, new balance is 0.0
39
account.withdraw(amount);
Thread.sleep(DELAY);
}
}
catch (InterruptedException exception)
{}
}
}
51
BankAccount.java
/**A bank account has a balance that can be changed by
deposits and withdrawals.*/
public class BankAccount{
private double balance;
public BankAccount(){
balance = 0;
}
public void deposit(double amount){
System.out.print("Depositing " + amount);
double newBalance = balance + amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
}
52
public void withdraw(double amount){
System.out.print("Withdrawing " +
amount);
double newBalance = balance - amount;
System.out.println(", new balance is " +
newBalance);
balance = newBalance;
}
public double getBalance(){
return balance;
}
}
53
Program Run:
Depositing 100.0, new balance is 100.0
Withdrawing 100.0, new balance is 0.0
Depositing 100.0, new balance is 100.0
Withdrawing 100.0, new balance is 0.0
...
Withdrawing 100.0, new balance is 400.0
Depositing 100.0, new balance is 500.0
Withdrawing 100.0, new balance is 400.0
Withdrawing 100.0, new balance is 300.0
54
synchronized
• Problem: race conditions
• Solution: give exclusive access to one thread at a time to
code that manipulates a shared object.
• Synchronization keeps other threads waiting until the
object is available.
• The synchronized keyword synchronizes the method so
that only one thread can access the method at a time.
• One way to correct the problem make Account thread-safe
by adding the synchronized keyword in deposit:
public synchronized void deposit(double amount)
55
Synchronizing Instance Methods
and Static Methods
• A synchronized method acquires a lock before it
executes.
• Instance method: the lock is on the object for which it
was invoked.
• Static method: the lock is on the class.
• If one thread invokes a synchronized instance method
(respectively, static method) on an object, the lock of that
object (respectively, class) is acquired, then the method is
executed, and finally the lock is released.
• Another thread invoking the same method of that object
(respectively, class) is blocked until the lock is released.
56
Synchronizing Instance Methods and
Static Methods
With the deposit method synchronized, the preceding scenario cannot
happen.
If Task 2 starts to enter the method, and Task 1 is already in the
method, Task 2 is blocked until Task 1 finishes the method.
Task 1 Task 2
-char to ken -char to ken
Acquire a lo ck o n the o bject
+ getToacco
ken unt + getTo ken
+ setTo ken + setTo ken
-char to ken + paintCo mpo net + paintCo mpo net
Execute the depo sit metho d
+ mo useClicked + mo useClicked
+ getTo ken Wait to acquire the lo ck
-char token
+ setTo ken
+ paintCo mp o net -char to ken
+
+ getTo ken Release the lo ck
mo useClicked
+ setTo ken
+ getTo ken
+ paintCo
-char mp o net
to ken Acqurie a lo ck o n the o bject acco unt
+ setTo ken
+ mo useClicked
+ paintCo mp o net
+ getTo ken -char to ken
+ mo useClicked
+ setTo ken
+ paintCo mp o net Execute
+ getTo ken the depo sit metho d
+ mo useClicked + setTo ken
-char
+ paintCo
to ken
mp o net
+ mo useClicked
+ getTo ken Release the lo ck
+ setTo ken
57
Synchronizing Statements
• Invoking a synchronized instance method of an object acquires a
lock on the object.
• Invoking a synchronized static method of a class acquires a lock
on the class.
• A synchronized block can be used to acquire a lock on any object,
not just this object, when executing a block of code.
synchronized (expr)
{ statements; }
• expr must evaluate to an object reference.
• If the object is already locked by another thread, the thread is
blocked until the lock is released.
• When a lock is obtained on the object, the statements in the
synchronized block are executed, and then the lock is released.
58
java.util.concurrent.locks.ReentrantLock
+ReentrantLock() Same as ReentrantLock(false).
+ReentrantLock(fair: boolean) Creates a lock with the given fairness policy. When the
fairness is true, the longest-waiting thread will get the
lock. Otherwise, there is no particular access order.
60
Fairness Policy
• ReentrantLock: concrete implementation of Lock for
creating mutually exclusive locks.
• Create a lock with the specified fairness policy.
• True fairness policies guarantee the longest-wait thread
to obtain the lock first.
• False fairness policies grant a lock to a waiting thread
without any access order.
• Programs using fair locks accessed by many threads may
have poor overall performance than those using the
default setting, but have smaller variances in times to
obtain locks and guarantee lack of starvation.
61