Threads Sync7 PDF

You might also like

You are on page 1of 3

Synchronization issues Locks

• Locks • All objects can be locked


• synchronized statements and methods • Only one thread can hold a lock on an object
– other threads block until they can acquire it
• wait and notify
• If your thread already holds a lock on an
• Deadlock object
– can lock it a second time
– object not unlocked until both locks released
• No way to only attempt to acquire a lock
CMCS 433, Spring 2002 - Adam Porter 1 CMCS 433, Spring 2002 - Adam Porter 2

Synchronized methods Synchronized statement

• A method can be synchronized • synchronized (obj) { statements }


– add synchronized modifier before return type • Obtains a lock on obj before executing
• Obtains a lock on object referenced by this, statements in block
before executing method • Releases lock once block completes
– releases lock when method completes • Provides finer grained control than
• For a static synchronized method synchronized method
– locks the class object • Allows locking arguments to a method
CMCS 433, Spring 2002 - Adam Porter 3 CMCS 433, Spring 2002 - Adam Porter 4

Synchronization example
Wait and Notify
class SyncTest extends Thread {
String msg;
public SyncTest(String s) {
msg = s;
• Must be called inside synchonized method
start(); } or block of statements (on the synchronized
public void run() {
synchronized (SyncTest.class) {
object)
System.out.print(“[“ + msg); • a.wait()
try { Thread.sleep(1000); }
catch (InterruptedException e) {}; – gives up lock(s) on a
System.out.println(“]”); } – adds thread to wait set for a
}
public static void main(String [] args) { – suspends thread
new SyncTest(“Hello”); new SyncTest(“Synchronized”);
new SyncTest(“World”); } • a.wait(int m)
} – limits suspension to m milliseconds
CMCS 433, Spring 2002 - Adam Porter 5 CMCS 433, Spring 2002 - Adam Porter 6

CMSC 433, Adam Porter, U. Maryland (via Bill Pugh) 1


Wait and Notify (cont.) Producer/Consumer Example
// Won’t work. Needs to handle
• a.notify() resumes one thread from a’s wait list // InterruptedException
– and removes it from wait set public class ProducerConsumer {
– no control over which thread private boolean ready = false;
private Object obj;
• a.notifyAll() resumes all threads on a’s wait list synchronized Object
public ProducerConsumer() { }
• resumed threads must reacquire lock before consume() {
public ProducerConsumer(Object o) {
while (!ready) wait();
continuing obj = o; ready = true; }
ready = false;
• wait doesn’t give up locks on any other objects notifyAll();
synchronized void produce(Object o) {
– e.g., acquired by methods that called this one return obj; }
while (ready) wait();
}
obj = o; ready = true;
CMCS 433, Spring 2002 - Adam Porter 7 notifyAll(); } CMCS 433, Spring 2002 - Adam Porter 8

A Better Solution
Changed example
void produce(Object o) {
while (bufFull) { synchronized (empty) {
synchronized void produce(Object o) {
try {empty.wait(); }
while (full) {
catch (InterruptedException e) { }
wait();
synchronized Object consume() { }}
if (full) notify(); } Object consume() {
while (!full) { obj = o; bufFull = true;
obj = o; full = true; while (!bufFull) { synchronized (full)
wait(); synchronized (full) {
notify(); {
if (!full) notify(); } full.notify(); }
} try { full.wait(); }
full = false; }
notify(); catch (InterruptedException e) {}
Use two objects, }}
Bad design – no return obj;
empty and full, to Object o = obj; bufFull = false;
guarantee about who }
allow two different synchronized (empty) {
will get woken up wait sets empty.notify(); }
CMCS 433, Spring 2002 - Adam Porter 9 CMCS 433, Spring 2002 - Adam Porter 10
}

notify() vs. notifyAll() InterruptedException Example

• Very tricky to use notify() correctly • Threads t1 and t2 are waiting


– notifyAll() much safer • Thread t3 performs a notify
• Need: – thread t1 is selected
– all waiters are equal • Before t1 can acquire lock, t1 is interrupted
– each notify only needs to wake up 1 thread • t1’s call to wait throws InterruptedException
– handle InterruptedException correctly – t1 doesn’t process notification
– t2 doesn’t wake up

CMCS 433, Spring 2002 - Adam Porter 11 CMCS 433, Spring 2002 - Adam Porter 12

CMSC 433, Adam Porter, U. Maryland (via Bill Pugh) 2


Handling InterruptedException Deadlock
• Quite possible to create code that deadlocks
synchronized (this) {
– Thread 1 holds lock on A
while (!ready) {
try { wait(); } – Thread 2 holds lock on B
catch (InterruptedException e) { – Thread 1 is trying to acquire a lock on B
notify(); – Thread 2 is trying to acquire a lock on A
throw e; } – Deadlock!
// do whatever • Not easy to detect when deadlock has
} occurred
} – other than by the fact that nothing is happening
CMCS 433, Spring 2002 - Adam Porter 13 CMCS 433, Spring 2002 - Adam Porter 14

Guidelines to simple/safe multi-


A common multi-threading bug
threaded programming
• Threads might cache values
• Obtaining a lock forces the thread to get fresh • Synchronize access to shared data
values • Don’t hold a lock on more than one object at a
• Releasing a lock forces the thread to flush out all time
pending writes – could cause deadlock
• volatile variables are never cached • Hold a lock for as little time as possible
• sleep(…) doesn’t force fresh values – reduces blocking waiting for locks
• Many compilers don’t perform these optimizations • While holding a lock, don’t call a method you
– but some do (Hotspot?)
don’t understand
– e.g., a method provided by someone else, especially if
• Problem might also occur with multiple CPUs you can’t be sure what it locks
CMCS 433, Spring 2002 - Adam Porter 15 CMCS 433, Spring 2002 - Adam Porter 16

Guidelines (cont.)

• Have to go beyond these guidelines for


more complex situations
– but need to understand threading and
synchronization well
• Recommended book for more details:
– Concurrent Programming in Java, by Doug
Lea

CMCS 433, Spring 2002 - Adam Porter 17

CMSC 433, Adam Porter, U. Maryland (via Bill Pugh) 3

You might also like