Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Programming with
Concurrent Threads
Robert M. Dondero, Ph.D.
Princeton University
1
Objectives
You will learn/review:
What a thread is
How to spawn and join threads
How to handle threads that access shared
objects
Race conditions and prevention of them
Deadlocks and prevention of them
How to interrupt threads
How threads can communicate
2
Definition of Thread
A process is an instance of a running
program
A thread is a flow of control within a
process
A process contains one or more threads
Within a process, all threads:
Execute concurrently
Share global data (data in the heap section,
data section, and bss section)
3
Concurrency Options
To implement concurrency...
Option 1: Multiple processes
Process P1 forks process P2
P1 and P2 execute concurrently
P1 and P1 do not share objects
Expensive context switching
4
Concurrency Options
Option 2: Multiple threads
Within P1, thread T1 spawns thread T2
T1 and T2 execute concurrently
T1 and T2 share P1’s objects
Inexpensive context switching
5
Processes vs. Threads
Concurrent Processes Running Same Program
PROCESS 1
HEAP
STACK
PROCESS 2
RODATA
STACK
DATA
HEAP
DATA
TEXT
BSS
BSS
IP REG
IP REG
6
Processes vs. Threads (cont.)
Concurrent Threads within Same Process
THREAD 1
STACK
THREAD 2
RODATA
DATA
HEAP
BSS
IP REG
STACK
IP REG
TEXT
7
The Usefulness of Threads
Example: Java virtual machine process
JVM process must execute given program
JVM process also must collect garbage
Example: server process
Server process must communicate with client
process continuously
Server process also must allow other client
processes to connect
8
The Usefulness of Threads
Example: browser process
Browser process must fetch (large) web pages
Browser process also must respond to user
input
9
Spawning Threads
The "main" thread executes at process
startup
Other threads may execute also
The main thread can spawn other threads
Note terminology:
One process "forks" another
One thread "spawns" another
10
Spawning Threads in Java
See Spawning.java
To spawn a thread:
Define a subclass of Thread
Override run() method
Create an object of that class
To begin execution of a thread:
Call object's start() method
start() calls run()
Don’t call run() directly
11
Spawning Threads in Java
See RunnableInterface.java
Alternative way to spawn a thread:
Define class that implements Runnable
Must define a run() method
Create a Thread object specifying
Runnable object as argument
12
Spawning Threads in Java
To begin execution:
Call Runnable object’s start() method
start() calls run()
Don't call run() directly
Useful when class extends some class other
than Thread
13
Spawning Threads in Python
See spawning.py
(Much the same as Java)
No need for "Runnable interface" approach
Python supports multiple inheritance
14
Joining Threads
Main thread can join a child thread
Main thread can block until child thread exits
Terminology
A parent process can "wait" for a child
process
A parent thread can "join" a child thread
15
Joining Threads in Java
See Joining.java
thread.join()
Blocks current thread until thread
terminates
May throw InterruptedException
(Explained later)
16
Joining Threads in Python
See joining.py
(Much the same)
17
Race Conditions
Problem:
Threads share objects
Danger if multiple threads update same object
Race condition
Outcome depends upon thread scheduling
See RaceCondition.java
See racecondition.py
18
Locking
Solution: Locking
Current thread gets lock on shared object
Other threads cannot obtain lock on shared
object until current thread releases lock
Adds lots of overhead
19
User-Level Locking
Approach 1: Locking in user of shared
object
20
User-Level Locking in Java
See LockInUser.java
synchronized(sharedobj)
{ stmt; stmt; …}
Current thread: "Make sure I have the lock on
sharedobj"
Other threads cannot obtain lock on sharedobj
during execution of block
21
User-Level Locking in Python
See lockinuser.py
First create a lock
bankLock = allocate_lock()
Then, in each thread:
self._bankLock.acquire()
Current thread: "Give me the lock on
sharedobj"
Use shared object
self._bankLock.release()
22
Resource-Level Locking
Approach 2: Locking in shared
resource/object itself
23
Java Resource-Level Locking
See LockInResource.java
public synchronized void method()
{…}
Is the same as:
public void method()
{ synchronized(this)
{…}
}
Bank object thus is thread-safe
24
Py Resource-Level Locking
See lockinresource.py
Same, except...
Locking is performed by bank object rather
than by thread objects
Bank object thus is thread-safe
25
Locking Strategies
Which locking approach is better?
Resource-level locking
Safer; shared object is thread-safe
User-level locking
Maybe faster
Avoids using locks when unnecessary
Recall Java Vector class vs. ArrayList
and SynchronizedList classes
26
Conditions
Problem:
Thread may need to wait for some condition
on a locked object to become true
Example:
Withdraw thread must wait for bank
balance to be sufficiently large
Solution: Conditions
27
Conditions
Called from within locked code…
object.wait()
Blocks current thread until it is notified
Releases lock
object.notifyAll()
Notifies all waiting threads
That some significant event has occurred
Thread then should re-check condition
28
Conditions Pattern
Thread conditions pattern:
consumer()
while (! condition)
wait();
// Do what should be done when
// condition is true.
producer()
// Change condition.
notifyAll();
29
Java Conditions
See Conditions.java
Consumer method calls object.wait()
repeatedly until condition is true
Producer method calls object.notifyAll()
Could handle conditions in users rather than in
shared resource
30
Python Conditions
See conditions.py
Condition wraps around lock
Could handle conditions in users rather than in
shared resource
31
Deadlock
Problem: deadlock
Two threads: t1 and t2
Two shared objects: o1 and o2
t1 has lock on o1; needs lock on o2
t2 has lock on o2; needs lock on o1
Both threads block forever
32
Java Deadlock Example
See Deadlock.java
Deadlock
(1) run()
(2) run()
chatThreadAlice
chatThreadBob
(3) chat()
alice
(4) chat()
(5) chatBack()
bob
(6) chatBack()
33
Python Deadlock Example
See deadlock.py
(Same formula)
34
Preventing Deadlock
Solution
System does not – and cannot – prevent
deadlock
Must design carefully to avoid deadlock
35
Java Preventing Deadlock
See NoDeadlock.java
NoDeadlock
(1) run()
chatThreadAlice
(3) chat()
alice
(2) run()
PersonMutex
(5) get lock
chatThreadBob
(7) get lock
(6) chatBack()
(8) chatBack()
(4) chat()
bob
36
Python Preventing Deadlock
See stilldeadlock.py
Still deadlock!
Note subtle difference in locking semantics
Java: "Make sure I have the lock"
Python: "Give me the lock"
See nodeadlock.py
Must do user-level locking
37
Interrupting Threads
Bad idea to end a thread abnormally
May leave shared objects in inconsistent
states
How to force normal thread termination?
That is, how to force normal return from run()?
38
Interrupting Threads
Forcing normal thread termination
Define isInterrupted flag in thread object
Define public thread.setInterrupted() method
Initially set to false
Called to set isInterrupted flag to true
run() checks isInterrupted flag periodically
true => return from run()
39
Interrupting Threads
Problem
What if thread is joining/waiting/sleeping?
Solution
Interrupting threads…
40
Java Interrupting Threads
thread.interrupt()
Sets flag
If thread is joining, waiting, or sleeping...
join(), wait(), or sleep() throws
InterruptedException
catch clause should forward interrupt to
current thread
Thread.interrupted()
Checks flag of current thread
Unsets flag
41
Java Interrupting Threads
Pattern:
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
See Interrupting.java
42
Python Interrupting Threads
Not supported!!!
(Java is particularly good for multithreaded programming)
43
Thread Communication
Facts:
Threads can communicate via shared objects
Communication via shared objects is
dangerous
Often threads are in a producer/consumer
relationship
Is there a safer way for producer/consumer
threads to communicate?
44
Java Thread Comm
ProducerThread
PipedOutputStream
ConsumerThread
PipedInputStream
PipedOutputStream and PipedInputStream
• Allow producer thread to send data to consumer thread
• See also java.io.PipedWriter and PipedReader for
sending Unicode characters
See ProdConStream.java
45
Python Thread Comm
See prodconstream.py
No "stream" mechanism
Can't implement Unix model
Instead...
Queue class
Methods are "synchronized"
Producer thread "puts" to queue object
Consumer thread "gets" from queue object
46
Threads Editorial
Today, threads are essential
Garbage collection, GUI pgmming, network
pgmming, Web pgmming, ...
Threads can be dangerous!!!
Threads share data, bss, heap sections
Avoid shared objects!!!
47
Threads Editorial
Should "synchronized" be the default?
Should safety or speed have priority?
Are threads a passing phase?
Summary
We have covered:
What a thread is
How to spawn and join threads
How to handle threads that access shared
objects
Race conditions and prevention of them
Deadlocks and prevention of them
How to interrupt threads
How threads can communicate
49
Appendix 1:
Threads in C
50
Threads in C
C language does not support threads
C standard library does not support
threads
Use non-standard "pthreads" library
Not object-oriented; uses function pointers
Specify “-pthread” option to gcc command
51
Threads in C
An error-handling module
See mypthread.h
See mypthread.c
Spawning threads
See spawning.c
52
Threads in C
Joining threads
See joining.c
Locking
See lockinuser.c
See lockinresource.c
Conditions
See conditions.c
53
Threads in C
Deadlock
See deadlock.c
See nodeadlock.c
Interrupting
(Not available in C)
Thread communication
(Omitted)
54
Appendix 2:
Daemon Threads
55
Daemon Threads
User thread (as seen so far)
Process exits when all user threads have
terminated
Example: thread that calls main()
Daemon thread
Exists only to service other threads
Process can terminate with running daemon
threads
Example: garbage collector thread
56
Daemon Threads
thread.setDaemon(b)
thread.isDaemon()
Sets daemon status of thread to b (true or
false)
Returns daemon status of thread
See Daemons.java
Daemon threads end when main thread ends
57