Download Programming with Concurrent Threads Robert M. Dondero, Ph.D. Princeton University

Document related concepts

Scheduling (computing) wikipedia , lookup

Transcript
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