Download Threads and Synchronization - Lecture Slides | CMSC 433 and more Study notes Programming Languages in PDF only on Docsity!
CMSC 433 – Programming Language
Technologies and Paradigms
Fall 2004
Threads and Synchronization
Nov 9, 2004
(thanks to Doug Lea for some slides)
54
Avoiding Interference:
Synchronization
public class Example extends Thread {
private static int cnt = 0;
static Object lock = new Object();
public void run() {
synchronized (lock) {
int y = cnt;
cnt = y + 1;
Lock , for protecting
the shared state
Acquires the lock;
Only succeeds if not
held by another
thread
Releases the lock
55
Applying Synchronization
int cnt = 0; t1.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } } t2.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } }
Shared state cnt = 0
T1 acquires the lock
56
Applying Synchronization
int cnt = 0; t1.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } } t2.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } }
Shared state cnt = 0
T1 reads cnt into y
y = 0
57
Applying Synchronization
int cnt = 0; t1.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } } t2.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } }
Shared state cnt = 0
T1 is pre-empted.
T2 attempts to
acquire the lock but fails
because it’s held by
T1, so it blocks
y = 0
58
Applying Synchronization
int cnt = 0; t1.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } } t2.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } }
Shared state cnt = 1
T1 runs, assigning
to cnt
y = 0
59
Applying Synchronization
int cnt = 0; t1.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } } t2.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } }
Shared state cnt = 1
T1 releases the lock
and terminates
y = 0
60
Applying Synchronization
int cnt = 0; t1.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } } t2.run() { synchronized(lock) { int y = cnt; cnt = y + 1; } }
Shared state cnt = 1
T2 now can acquire
the lock.
y = 0
65
Synchronized Methods
• A method can be synchronized
- Add synchronized modifier before return type
• Obtains the lock on object referenced by this
before executing method
- Releases lock when method completes
• For a static synchronized method
- Locks the Class object for the class
- Accessible directly, e.g. Foo.class
- Not the same as this!
66
Synchronization Example
public class State { private int cnt = 0; public int synchronized incCnt(int x) { cnt += x; } public int synchronized getCnt() { return cnt; } } public class MyThread extends Thread { State s; public MyThread(State s) { this.s = s; } public void run() { s.incCnt(1) } public void main(String args[]) { State s = new State(); MyThread thread1 = new MyThread(s); MyThread thread2 = new MyThread(s); thread1.start(); thread2.start(); } }
Synchronization
occurs in State
object itself,
rather than in
its caller.
67
Synchronization Style
• Design decision
- Internal synchronization (class is thread-safe)
- Have a stateful object synchronize itself (e.g., with synchronized methods)
- External synchronization (class is thread-compatible)
- Have callers perform synchronization before calling the object
• Can go both ways:
- Thread-safe: Random
- Thread-compatible: ArrayList, HashMap, …
68
Synchronization not a Panacea
• Two threads can block on locks held by the
other; this is called deadlock
Object A = new Object(); Object B = new Object(); T1.run() { synchronized (A) { synchronized (B) { … } } }
T2.run() { synchronized (B) { synchronized (A) { … } } }
69
Deadlock
• Quite possible to create code that deadlocks
– Thread 1 holds lock on A
– Thread 2 holds lock on B
– Thread 1 is trying to acquire a lock on B
– Thread 2 is trying to acquire a lock on A
– Deadlock!
• Not easy to detect when deadlock has
occurred
– Other than by the fact that nothing is happening
70
Deadlock: Wait graphs
A T1 Thread T1 holds lock A
T2 B
Thread T2 attempting to
acquire lock B
Deadlock occurs when there is a cycle in the graph
71
Wait graph example
A T
T2 B
T1 holds lock on A
T2 holds lock on B
T1 is trying to acquire a lock on B
T2 is trying to acquire a lock on A
72
Key Ideas
• Multiple threads can run simultaneously
- Either truly in parallel on a multiprocessor
- Or can be scheduled on a single processor
- A running thread can be pre-empted at any time
• Threads can share data
- In Java, only fields can be shared
- Need to prevent interference
- Synchronization is one way, but not the only way
- Overuse use of synchronization can create deadlock
77
Wait and Notify
• Both must be called while lock is held on a
• a.wait()
– Releases the lock on a
- But not any other locks acquired by this thread
– Adds the thread to the wait set for a
– Blocks the thread
• a.wait(int m)
– Limits wait time to m milliseconds
78
Wait and Notify (cont.)
• a.notify() resumes one thread from a ’s wait
set
– No control over which thread
• a.notifyAll() resumes all threads on a ’s
wait set
• Resumed thread(s) must reacquire lock
before continuing
– Java performs the reacquire automatically
This document was created with Win2PDF available at http://www.daneprairie.com.
The unregistered version of Win2PDF is for evaluation or non-commercial use only.