1
11. Multithreaded Applications
3/10/2018
John Roberts
2
Overview
• What is a thread?
• Thread class
• Runnable interface
• Thread states
• Controlling threads
• Synchronization
3
What is a process?
• An instance of a computer program that is being
executed
• Contains the program code, and its current activity:
• Machine code
• Memory (includes code, process specific data, call
stack, and heap)
• State (content of registers, Program Counter, Stack
Pointer, etc.)
4
What is a thread?
• The smallest sequence of programmed instructions that
can be managed independently by a schedule (typically
part of the OS)
• Contained within a process
• A single path of execution within a process
• Shares resources within a process
• Processes have their own address space, threads
share their address space
5
Processes vs. Threads
• Threads are “lightweight processes”
• Communication between threads is accomplished by
accessing shared memory, processes must use relatively
more expensive IPC (files, sockets, pipes)
• Context switches between threads are cheaper
(processes must swap out a memory space, thread
memory space is shared)
6
Multithreading
Multiple threads running on multiple processors
Thread 1
Thread 2
Thread 3
Multiple threads sharing a single CPU
Thread 1
Thread 2
Thread 3
7
Overview
• What is a thread?
• Thread class
• Runnable interface
• Thread states
• Controlling threads
• Synchronization
8
Thread class
• Java docs
• To create a new thread of execution, we can subclass
Thread, and implement the run method
9
Objective
• Create and execute three threads
• One prints the letter a 100 times
• One prints the letter b 100 times
• One prints the numbers from 1 to 100
• Github
10
LetterThread
1 public class LetterThread extends Thread {
2 private char character;
3
4 public LetterThread( char character ) {
5 this.character = character;
6 }
7
8 public void run() {
9 for( int counter = 0; counter < 100; counter++ ) {
10 System.out.print( this.character + " " );
11 }
12 }
13 }
11
CounterThread
1 public class CounterThread extends Thread {
2 public void run() {
3 for( int counter = 1; counter <= 100; counter++ ) {
4 System.out.print( counter + " " );
5 }
6 }
7 }
12 What will this print out when I run it? When I run it again?
Client
(make command cleans, compiles, and runs)
1 public class Client {
2 public static void main( String[] args ) {
3 LetterThread a = new LetterThread( 'a' );
4 LetterThread b = new LetterThread( 'b' );
5 CounterThread c = new CounterThread();
6
7 a.start();
8 b.start();
9 c.start();
10 }
11 }
13
Overview
• What is a thread?
• Thread class
• Runnable interface
• Thread states
• Controlling threads
• Synchronization
14
Runnable Interface
• Java docs
• To create a new thread of execution, we can implement
the Runnable interface, and implement the run method
• Create a new Thread with the Runnable instance
15
Objective
• Create and execute three threads
• One prints the letter a 100 times
• One prints the letter b 100 times
• One prints the numbers from 1 to 100
• Github
16
extend Thread vs. implement Runnable
• Why would we want to do one over the other?
17 r is reused, so any state in r can be shared among the two threads
extend Thread vs. implement Runnable
running it
• Why would we want to do one over the other?
• You can only extend only one class, constraining your class
design (rooting the class hierarchy at Thread)
• Runnables can be shared among Threads, allowing us to
access common resources
CustomThread a = new CustomThread();
CustomThread b = new CustomThread();
CustomRunnable r = new CustomRunnable();
new Thread( r ).start();
new Thread( r ).start();
18 No difference between this and LetterThread
LetterRunnable
1 public class LetterRunnable implements Runnable {
2 private char character;
3
4 public LetterRunnable( char character ) {
5 this.character = character;
6 }
7
8 public void run() {
9 for( int counter = 0; counter < 100; counter++ ) {
10 System.out.print( this.character + " " );
11 }
12 }
13 }
19 No difference between this and CounterThread
CounterRunnable
1 public class CounterRunnable implements Runnable {
2 public void run() {
3 for( int counter = 1; counter <= 100; counter++ ) {
4 System.out.print( counter + " " );
5 }
6 }
7 }
20 Stylistically, I’m not a fan of the temp variables, this could be made
Client
more concise (YMMV):
1 public class Client {
2
3
public static void main( String[] args ) {
LetterRunnable a = new LetterRunnable( 'a' );
new Thread( new LetterRunnable( ‘a’) ).start();
4 LetterRunnable b = new LetterRunnable( 'b' );
5 CounterRunnable c = new CounterRunnable();
6
7 new Thread( a ).start();
8 new Thread( b ).start();
9 new Thread( c ).start();
10 }
11 }
21
Overview
• What is a thread?
• Thread class
• Runnable interface
• Thread states
• Controlling threads
• Synchronization
22
Thread States
Thread Created
ready stop finished
resume, notify,
start run or notifyAll
stop, or complete stop
new yield, or time
expired
suspend, sleep,
running blocked
or wait
23
Overview
• What is a thread?
• Thread class
• Runnable interface
• Thread states
• Controlling threads
• Synchronization
24 Note that Thread implements runnable (so both Threads and
Controlling Threads
Runnables are runnables)
• void run()
Invoked by the Java runtime system to execute the
thread. You must override this method and provide the
code you want your thread to execute (but you will not
invoke this method!)
• void start()
Starts the thread, which causes the run() method to be
invoked. Called by the runnable object in the client class.
25
Controlling Threads
• static void sleep( long milliseconds )
throws InterruptedException
Puts the runnable object to sleep (temporarily cease
execution) for a specified time in milliseconds
• public final void join() throws
InterruptedException
Allows one thread to wait for the completion of another
26
Overview
• What is a thread?
• Thread class
• Runnable interface
• Thread states
• Controlling threads
• Synchronization
27 Showing the possible case where thread execution switches at each
Synchronization
time step
• Shared resources could become corrupted if accessed
simultaneously by multiple threads
time balance thread A thread B
1 0 newBalance = bank.getBalance() +1
2 0 newBalance = bank.getBalance() +1
3 1 bank.setBalance( newBalance );
4 1 bank.setBalance( newBalance );
28
Piggy Bank
1 public class PiggyBank {
2 private int balance = 0;
3
4 public int getBalance() {
5 return this.balance;
6 }
7
8 public void setBalance( int newBalance ) {
9 this.balance = newBalance;
10 }
11 }
29 https://github.com/sfsu-csc-413-roberts/lecture-11/tree/master/piggy-
Add a Penny Thread, Unsynchronized
bank
1 public class AddAPennyThreadUnsynchronized extends Thread {
2
3
private PiggyBank bank; Arbitrary sleep to force interruption…
4 public AddAPennyThreadUnsynchronized( PiggyBank bank ) {
5 this.bank = bank;
6 }
7
8 public void run() {
9 int newBalance = bank.getBalance() + 1;
10
11 try {
12 Thread.sleep( 5 );
13 } catch( InterruptedException e ) {
14 System.out.println( "Interrupted" );
15 }
16
17 bank.setBalance( newBalance );
18 }
19 }
30
Synchronized Methods
• Java Tutorial
• To make a method synchronized, add the synchronized
keyword to its declaration:
public synchronized void someMethod() { /* … /* }
• When one thread is executing a synchronized method for
an object, all other threads that invoke synchronized
methods for the same object will block (suspend execution)
• Constructors can not be synchronized!
31
Locks
• Every object has an intrinsic lock associated with it
• Enforces exclusive access to an object’s state
• A thread that needs exclusive and consistent access to
an object’s state has to acquire the lock before
accessing them
• If another thread has already acquired the lock, then
the current thread must wait until the lock is released
• A thread releases the lock when done
32
Locks
• The intrinsic lock used with a synchronized method
controls only access to the current object
• We may also use the lock on the Class object associated
with the class, with a static synchronized method
declaration (see next slide)
33 Line 14 means that the *current thread* (main) should wait for
PiggyBank Driver
pennies[i] to complete - this line tells the current thread to wait until all
penny threads have completed execution.
1 public class PiggyBankDriver {
2 public static void main( String[] args ) throws InterruptedException {
3 final int count = 100;
4
5 PiggyBank bank = new PiggyBank();
6 Thread pennies[] = new Thread[ count ];
7
8 for( int i = 0; i < count; i++ ) {
9 pennies[ i ] = new AddAPennyThread( bank );
10 pennies[ i ].start();
11 }
12
13 for( int i = 0; i < count; i++ ) {
14 pennies[ i ].join();
15 }
16
17 System.out.println(
18 "After adding " + count + " pennies, balance is " + bank.getBalance()
19 );
20 }
21 }
34 https://github.com/sfsu-csc-413-roberts/lecture-11/tree/master/piggy-
Add a Penny Thread, with Synchronization
1 public class AddAPennyThreadSynchronized extends Thread {
bank-synchronized
static synchronized is using a lock obtained from the class - what
2 private PiggyBank bank;
3
4 public AddAPennyThreadSynchronized( PiggyBank bank ) {
5 this.bank = bank;
6
7
}
happens if we omit static (and change the run method accordingly)?
8 private static synchronized void addAPenny( PiggyBank bank ) {
9
10
11
int newBalance = bank.getBalance() + 1;
try {
Synchronization is happening on the thread, not on the PiggyBank
object! (We could change the implementation of PiggyBank for more
12 Thread.sleep( 5 );
13 } catch( InterruptedException e ) {
14 System.out.println( "Interrupted" );
15 }
16
17
18 }
bank.setBalance( newBalance ); intuitive access control…)
19
20 public void run() {
21 addAPenny( this.bank );
22 }
23 }
35 Guess which one is synchronized
Sample Outputs
ᐅ make
find . -type f -name '*.class' -delete
javac PiggyBankDriver.java; java PiggyBankDriver
After adding 100 pennies, balance is 1
ᐅ make
find . -type f -name '*.class' -delete
javac PiggyBankDriver.java; java PiggyBankDriver
After adding 100 pennies, balance is 2
ᐅ make
find . -type f -name '*.class' -delete
javac PiggyBankDriver.java; java PiggyBankDriver
After adding 100 pennies, balance is 100