190 likes | 360 Views
Deadlock. DeadlockedBankAccount withdraw(){ lock.lock(); while(balance <= 0){ System.out.print("W"); // waiting for the balance to exceed 0 Thread.sleep(1000); } balance -= amount; lock.unlock(); }
E N D
Deadlock • DeadlockedBankAccount • withdraw(){ lock.lock();while(balance <= 0){ System.out.print("W"); // waiting for the balance to exceed 0 Thread.sleep(1000); } balance -= amount; lock.unlock(); } • deposit(){ lock.lock();while(balance > 10000){ System.out.print("W"); // waiting for the balance to go below 10000 Thread.sleep(1000) } balance += amount; lock.unlock(); }
Output: DeadlockedBankAccount • Lock obtained • Current balance (d): 0.0WWWWWWW
DeadlockedBankAccount2 • publicvoid deposit(double amount){while( balance > 10000 ){System.out.print("W");Thread.sleep(2);}lock.lock();balance += amount;lock.unlock();} • publicvoid withdraw(double amount){while( balance <= 0 ){ System.out.print("W"); Thread.sleep(2);}lock.lock();balance -= amount;lock.unlock();}
Lock obtained • WCurrent balance (d): 0.0, New balance (d): 100.0 • Lock released • Lock obtained • Current balance (w): 100.0, New balance (w): 0.0 • Lock released • Lock obtained • Current balance (d): 0.0, New balance (d): 100.0 • Lock released • Lock obtained • Current balance (w): 100.0, New balance (w): 0.0 • Lock released • Lock obtained • Current balance (d): 0.0, New balance (d): 100.0 • Lock released
Lock obtained • WCurrent balance (d): 0.0, New balance (d): 100.0 • Lock released Deposit thread Withdraw thread If(balance <= 0) --> true print out “W” sleep Gain a time slice Reaches the end ofits time slice Acquire a lock print(“current balance…); // 0balance += amount;// balance --> 100println(“new balance…); // 100 Release a lock Gain a time slice Reaches the end ofits time slice (balance=100) If(balance <=0) --> false Withdraw money
DeadlockBankAccount2 has no deadlock problems. • However, it is not completely thread safe. • Why?
Deposit thread Withdraw thread If(balance <= 0) --> true Reaches the end ofits time slice Gain a time slice Acquire a lock print(“current balance…); // 0balance += amount;// balance --> 100println(“new balance…); // 100 Release a lock Gain a time slice Reaches the end ofits time slice (balance=100) print out “W”sleep() If(balance <=0) --> false Withdraw money These two lines are not supposed to beexecuted when balance > 0.
Avoiding Deadlocks • Use Condition objects • Allow a thread to • temporarily release a lock so that another thread can proceed • The thread goes to the Waiting state from the Runnable state. • re-acquire the lock at a later time. • java.util.concurrent.locks.Condition • Obtain its instance from a lock object • private ReentrantLock lock;Condition condition = lock.newCondition();condition.await();
Waiting TimedWaiting sleep()join()wait()await() notify()notifyAll()signalAll()interruption notify()notifyAll()signalAll() interruption sleep()join()wait()await() Exits run() or Explicit threadtermination Runnable Terminated new New start() I/O op completionor thread sync done I/O operation or wait for thread sync (lock) Blocked
ThreadSafeBankAccount2 • Condition sufficientFundsCondition = lock.newCondition();Condition belowUpperLimitFundsCondition = lock.newCondition(); • withdraw(double amount){ lock.lock();while(balance < amount){ // waiting for the balance to exceed “amount” sufficientFundsCondition.await(); } balance -= amount; lock.unlock();belowUpperLimitFundsCondition.signalAll(); } • deposit(double amount){ lock.lock();while(balance >= 300){ // waiting for the balance to go below the upper limit. belowUpperLimitFundsCondition.await(); } balance += amount; lock.unlock();sufficientFundsCondition.signalAll(); }
Condition • await() • Until it is signaled or interrupted • Until it is signaled or interrupted, or a specified waiting time (relative time) elapsed. • Until it is signaled or interrupted, or a specified deadline (absolute time) time elapsed. • signalAll() • Wakes up all the threads waiting on this condition. • There is no guarantee about which thread will acquire a lock. • signal() • Wakes up one of the threads waiting on this condition. • There is no guarantee about which thread is waked up.
ThreadSafeBankAccount2 • Output • Lock obtained • 7 (d): current balance: 0.0 • 7 (d): new balance: 100.0 • Lock released • Lock obtained • 8 (d): current balance: 100.0 • 8 (d): new balance: 200.0 • Lock released • Lock obtained • 9 (d): current balance: 200.0 • 9 (d): new balance: 300.0 • Lock released • Lock obtained • 10 (d): current balance: 300.0 • 10 (d): await(): Balance exceeds the upper limit. • Lock obtained • 11 (d): current balance: 300.0 • 11 (d): await(): Balance exceeds the upper limit. • Lock obtained • 12 (w): current balance: 300.0 • 12 (w): new balance: 200.0 • Lock released • 10 (d): new balance: 300.0 • Lock released • 11 (d): await(): Balance exceeds the upper limit.
Thread Synchronization Tools • Lock (or mutex) • java.util.concurrent.locks.ReentrantLock • Reader-writer locks • java.util.concurrent.locks.ReentrantReadWriteLock • java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock • java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock • Semaphore • java.util.concurrent.Semaphore • Barrier • java.util.concurrent.CyclicBarrier
Reader-Writer Locks • Special types of lock • Lock • Shared data must be locked when it is being changed/written. • Is data locking necessary among read-only threads? • No. Read-only threads do not have to compete against each other to acquire a lock. • Why not being nice or optimistic about data locking for readers?
ReadWriteLock • ReentrantReadWriteLock • In java.util.concurrent.locks • ReentrantReadWriteLock{ public ReentrantReadWriteLock.ReadLock readLock(){} public ReentrantReadWriteLock.WriteLock writeLock(){} } • Provides two locks; a lock for writers, and the other for readers. • Readers obtain a read lock. • Writers obtain a write lock.
Readers can acquire a read lock even if it is already held by another reader, • AS FAR AS no writers holds a write lock. • Writers can acquire a write lock ONLY IF no other writers and readers hold read/write locks. Other threadsexist holding …? ReadLock WriteLock A threadtrying to acquirea lock ReadLock N Y WriteLock N N
ReentrantReadWriteLock.ReadLock • ReentrantReadWriteLock.WriteLock • Inner classes of ReentrantReadWriteLock • They are used only by ReentrantReadWriteLock; they should not be open/available for anything else. • Work similarly to ReentrantLock. • These locks support nested locking. • A condition object is returned when calling newCondition() on a write lock. • Calling newCondition() on a read lock generates an UnsupportedOperationException.
Sample Code • ThradSafeBankAccount3 • 43 msec • ThradSafeBankAccount4 • 33 msec • 23% (10/43) faster
When to Use ReadWriteLock? • When many readers run. • When readers run more frequently than writers. • When read operations take a long time.