Chapter 7 Multithreading Programming PDF
Chapter 7 Multithreading Programming PDF
Chapter Seven
Multithreading Programming
Multithreading 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
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
4
Threads Concept
Multiple Thread 1
threads on Thread 2
multiple Thread 3
CPUs
Multiple Thread 1
threads Thread 2
sharing a Thread 3
single CPU
5
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.
6
Thread States
7
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.
8
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 other threads to execute.
+interrupt(): void § Interrupts this thread.
11
The Static yield() Method
You can use the yield() method to temporarily release
time for other threads. For example,
public void run() {
for (int i = 1; i <= lastNum; i++) {
System.out.print(" " + i);
Thread.yield();
}
}
Every time a number is printed, the print thread is
yielded. So, the numbers are printed after the
characters.
12
The Static sleep(milliseconds) Method
The sleep(long mills) method puts the thread to sleep for
the specified time in milliseconds.
For example,
public void run() {
for (int i = 1; i <= lastNum; i++) {
System.out.print(" " + i);
try {
if (i >= 50) Thread.sleep(1);
}
catch (InterruptedException ex)
{ }
}
}
Every time a number (>= 50) is printed, the print100
thread is put to sleep for 1 millisecond.
13
Example: GreetingRunnable.java
import java.util.Date;
public class GreetingRunnable implements Runnable {
private static final int REPETITIONS = 10;
private static final int DELAY = 1000;
private String greeting;
public GreetingRunnable(String aGreeting){
greeting = aGreeting;
}
public void run(){
try{
for (int i = 1; i <= REPETITIONS; i++){
Date now = new Date();
System.out.println(now+” ”+ greeting);
Thread.sleep(DELAY);
}
}catch (InterruptedException exception) {}
}
}
14
The join() Method
You can use the join() method to force one thread to wait
for another thread to finish.
For example
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
19
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.
Thread Pools
20
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.
24
Thread Synchronization…
Example: two unsynchronized threads accessing the same bank
account may cause conflict.
AccountWithoutSync
Run
26
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();
}
}
}
34
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();
}
35
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();
}
}
36
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;
}
}
37
• 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
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
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
53
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)
54
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.
55
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 token -char token
Acquire a lock on the object
account
+ getToken + getToken
+ setToken + setToken
-char token + paintComponet + paintComponet
Execute the deposit method
+ mouseClicked + mouseClicked
+ getToken Wait to acquire the lock
-char token
+ setToken
+ paintComponet -char token
+
+ getToken Release the lock
mouseClicked
+ setToken
+ getToken
+ paintComponet
-char token Acqurie a lock on the object account
+ setToken
+ mouseClicked
+ paintComponet
+ getToken -char token
+ mouseClicked
+ setToken
+ paintComponet Execute the deposit method
+ getToken
+ mouseClicked + setToken
-char
+ paintComponet
token
+ mouseClicked
+ getToken Release the lock
+ setToken
56
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.
57
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.
59
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.
60
Cooperation Among Threads
• Conditions can be used for communication among threads.
• A thread can specify what to do under a certain condition.
• newCondition() method of Lock object.
• Condition methods:
• await() current thread waits until the condition is signaled
• signal() wakes up a waiting thread
• signalAll() wakes all waiting threads
61
Cooperation Among Threads
• Lock with a condition to synchronize operations: newDeposit
• If the balance is less than the amount to be withdrawn, the
withdraw task will wait for the newDeposit condition.
• When the deposit task adds money to the account, the task
signals the waiting withdraw task to try again.
• Interaction between the two tasks:
Withdraw Task Deposit Task