Download presentation
Presentation is loading. Please wait.
Published byWendy Cobb Modified over 8 years ago
1
CS 151: Object-Oriented Design November 26 Class Meeting Department of Computer Science San Jose State University Fall 2013 Instructor: Ron Mak www.cs.sjsu.edu/~mak
2
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 2 Thread Synchronization Example Recall the bounded queue object (circular buffer). Suppose it is shared among several threads. Two producer threads add messages. One adds “A Message” The other adds “B Message” Each prints the messages as it adds them. One consumer thread removes messages. Prints the messages as it removes them. _
3
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 3 Thread Synchronization, cont’d The run() method of the Producer class: int i = 1; while (i <= count) { if (!queue.isFull()) { Message msg = new Message(index, i, text); queue.add(msg);... i++; } Thread.sleep((int) (DELAY*Math.random())); }
4
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 4 Thread Synchronization, cont’d The run() method of the Consumer class: int i = 1; while (i <= count) { if (!queue.isEmpty()) { Message msg = queue.remove();... i++; } Thread.sleep((int) (DELAY*Math.random())); }
5
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 5 Thread Synchronization, cont’d Create the queue, and create and start the threads: BoundedQueue queue = new BoundedQueue(10); final int PRODUCER_C0UNT = 2; final int MESSAGE_COUNT = 100; Runnable run1 = new Producer("A Message", queue, 1, MESSAGE_COUNT); Runnable run2 = new Producer("B Message", queue, 2, MESSAGE_COUNT); Runnable run3 = new Consumer(queue, PRODUCER_C0UNT*MESSAGE_COUNT); Thread thread1 = new Thread(run1); Thread thread2 = new Thread(run2); Thread thread3 = new Thread(run3); thread1.start(); thread2.start(); thread3.start(); Demo: queue1
6
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 6 A Race Condition A race condition occurs when multiple threads access and modify some shared data, and the final result depends on the order that the threads modified the data. An extremely bad situation. Results are often unpredictable and unrepeatable. Extremely hard to debug. Must avoid! _
7
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 7 "Message B" "Message A"
8
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 8 Critical Region One way to avoid race conditions is to prevent more than one thread from reading and writing the shared data at the same time. This is called mutual exclusion. Thread schedulers provide different primitives to achieve mutual exclusion. A critical region (AKA critical section) is the part of a program’s code that operates on some shared data. We need to prevent two threads from accessing that shared data at the same time. Therefore, we need to prevent two threads from being in their critical regions at the same time.
9
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 9 A Solution: Locks When one thread enters its critical region, another thread must be prevented from entering its critical region. The first thread must set a lock before entering the critical region, execute the code in the critical region, and then unlock the lock. If another thread attempts to enter its critical region, that thread must wait until the lock is unlocked. Java provides re-entrant locks. Lock aLock = new ReentrantLock();... aLock.lock(); try { critical region } finally { aLock.unlock(); }
10
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 10 Locks, cont’d But is it sufficient to lock up the add() and remove() code of BoundedQueue ? _ Demo: queue2
11
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 11 Locks, cont’d Consider what the Producer does: Suppose the first Producer thread determined that the queue is not full. But before it can call queue.add(), another Producer thread fills up the queue. When the first Producer thread is reactivated, it adds to a full queue and thereby corrupts it. Therefore, testing whether the queue is full and adding to the queue must happen together under the same lock. if (!queue.isFull()) { Message msg = new Message(index, i, text); queue.add(msg);... }
12
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 12 Lock Conditions Each lock can have one or more Condition objects: Call await() on a Condition object to: Temporarily release the lock. Block the current thread and add it to the set of threads that are waiting on that condition. Call signalAll() on a condition to unblock all threads that are waiting on that condition. _ private Lock qLock = new ReentrantLock(); private Condition spaceAvailable = qLock.newCondition(); private Condition messageAvailable = qLock.newCondition();
13
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 13 Thread-Safe Adding to the Queue The producer’s critical region in BoundedQueue : public void add(Message newValue) throws InterruptedException { qLock.lock(); try { while (isFull()) spaceAvailable.await(); elements[tail] = newValue; tail++; size++; if (tail == elements.length) tail = 0; messageAvailable.signalAll(); } finally { qLock.unlock(); } Why a while loop and not simply an if statement?
14
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 14 Thread-Safe Removing from the Queue The consumer’s critical region in BoundedQueue : public Message remove() throws InterruptedException { qLock.lock(); try { while (isEmpty()) messageAvailable.await(); Messge msg = elements[head]; head++; size--; if (head == elements.length) head = 0; spaceAvailable.signalAll(); return msg; } finally { qLock.unlock(); } Demo: queue3
15
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 15 Synchronize the Printing The program is actually working, but the printing of the added and removed messages is out of sync. The printing was for debugging purposes. After a message is added to the queue but before it was printed, another add or remove operation can jump in. We must also move the message printing into the critical regions. _ Demo: queue4
16
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 16 Integrated Java Support for Multithreading So far, we’ve seen how Java supports multithreaded programming using special classes. Java also has multithreading support that’s more integrated into the language. _ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;
17
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 17 Java synchronized Methods Every Java object has an associated object lock. If an object’s method is tagged as synchronized, then when a thread calls, it tries to acquire (i.e., lock) the object lock. The thread blocks if another thread has already acquired the lock. Upon exit from the synchronized method, the object lock is automatically released (i.e., unlocked). Each object lock has one condition object. Call wait() to wait on that condition. Call notifyAll() when that condition has changed.
18
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 18 Java synchronized Methods In BoundedQueue : public synchronized void add(Message newValue) throws InterruptedException { while (isFull()) wait(); elements[tail] = newValue; tail++; size++; if (tail == elements.length) tail = 0;... notifyAll(); }
19
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 19 Java synchronized Methods In BoundedQueue : public synchronized Message remove() throws InterruptedException { while (isEmpty()) wait(); Message msg = elements[head]; head++; size--; if (head == elements.length) head = 0;... notifyAll(); return msg; } Demo: queue5
20
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 20 Locks and Condition Objects Use locks to protect shared data. Each piece of shared data has a set of corresponding critical regions. A thread accesses the shared data in its critical region. Create a shared lock to guard the critical regions that are associated with some shared data. Or use the built-in object lock. The lock prevents more than one thread from being in its critical region at a time. _
21
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 21 Locks and Condition Objects Use condition objects to synchronize threads. Create a condition object from a lock. Or use the built-in condition object from the object lock. Calling await() on a condition object temporarily releases a lock and blocks the current thread. Or call wait() on the built-in condition object. The current thread is added to the set of threads that are waiting for the condition. Calling signalAll() on a condition object unblocks all threads that are waiting for that condition. Or notifyAll() on the built-in condition object. _
22
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 22 Multithreaded Programming is Hard! The execution order of the threads is not guaranteed. Your program must work no matter what the order is. You must explicitly synchronize the threads. It is easy to corrupt shared objects. A thread must prevent another thread from “sneaking in” before it is finished with its operations. A thread must remember to signal other threads to prevent the program from deadlocking. Debugging is multithreaded programs is difficult. Different errors (or none at all) may occur on each run. Errors may be timing related. However, multithreaded programming is a critical job skill.
23
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 23 Assignment #6 Multithreaded RPS game server Play multiple RPS games simultaneously. Create a server window. Use this window to open up to three game windows. Your game window from Assignment #5. Each game window plays RPS against a human player. The server window displays: A running tally of wins and ties of each game. The total number of wins and ties across all the games. Smart computer algorithm support. _
24
SJSU Dept. of Computer Science Fall 2013: November 26 CS 151: Object-Oriented Design © R. Mak 24 Assignment #6 Smart computer algorithm support. Record the choice sequences from all the games. Whenever you terminate your game server, write your record of choice sequences out to a disk file. Whenever you restart your game server, read your record of choice sequences back in. Therefore, your program accumulates more and more sequences and becomes smarter and smarter. You need to: Identify the shared data. Identify the critical regions in your threads. Protect the critical regions and synchronize your threads. _
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.