Download presentation
Presentation is loading. Please wait.
1
Chapter 9 Multithreading
2
Chapter Topics Thread Basics Thread Synchronization Animations
3
Threads Thread: program unit that is executed independently
Multiple Threads: Program units what can be executed in parallel. Multiple threads run simultaneously. When executes Multiprocessor computers: threads actually run in parallel OR Illusion of threads running in parallel. That is, Virtual machine executes each thread for short time slice. Thread scheduler activates, deactivates threads.
4
Threads and the Runnable Interface Type (1)
How to implement Running Threads Define class that implements Runnable interface. Runnable has one method. void run() Place thread action into run() method Construct an object of the class which implements the Runnable Interface Construct an object of Thread class start() thread
5
Threads and the Runnable Interface Type (2)
public class MyRunnable implements Runnable { public void run() { thread action } ... Runnable r = new MyRunnable(); Thread t = new Thread(t); t.start();
6
Thread Example Run two threads in parallel Each thread
prints 10 greetings for (int i = 1; i <= 10; i++) { System.out.println(i + ": " + greeting); Thread.sleep(100); } After each printout, sleep for 100 milliseconds All threads should occasionally yield control sleep() throws InterruptedException
7
Thread Example (1) Ch9/greeting/GreetingProducer.java
Ch9/greeting/ThreadTester.java
8
Thread Example Sample Output (Note: output not exactly interleaved.)
1: Hello, World! 1: Goodbye, World! 2: Hello, World! 2: Goodbye, World! 3: Hello, World! 3: Goodbye, World! 4: Hello, World! 4: Goodbye, World! 5: Hello, World! 5: Goodbye, World! 6: Hello, World! 6: Goodbye, World! 7: Hello, World! 7: Goodbye, World! 8: Goodbye, World! 8: Hello, World! 9: Goodbye, World! 9: Hello, World! 10: Goodbye, World! 10: Hello, World! The thread scheduler gives no guarantee about the order in which threads are executed. Moreover, there will always be slight variations in running times, especially when calling operating system services (such as input and output). Thus, you should expect that the order in which each thread gains control appears to be somewhat random.
9
Starting Two Threads
10
Thread States Each thread has Thread states: thread state priority new
before start() called runnable blocked dead after run() method exits
11
Blocked Thread State Reasons for entering the blocked state:
Sleeping Waiting for I/O Waiting to acquire lock (later) Waiting for condition (later) Unblocks only if the reason for the blocking goes away
12
Scheduling Threads Scheduler activates a new (next) thread if
a thread has completed its time slice a thread has blocked itself a thread with higher priority has become runnable Scheduler determines a new thread to run by looking only at all runnable threads, and picking one with the highest priority value. (The priority values are system-dependant and not adjustable by an application programmer.) OR Picking one at random or using a round-robin scheme to gives each thread a chance.
13
Terminating Threads (1)
Normal way to terminate a thread Thread terminates when run() exits However, you sometimes need to terminate running thread (Ex) you may have several threads attempting to find a solution to a problem. As soon as the first one has succeeded, you can terminate the other ones.
14
Terminating Threads (2)
Interrupt thread by calling interrupt() Don't use deprecated stop() method It is deprecated since the method can hold a shared resource and does not release it. Calling t.interrupt() doesn't actually interrupt t; just sets a “interrupted” flag The run() method should check whether its thread has been interrupted. In that case, it should do any necessary cleanup and exit. The most practical strategy for dealing with thread interruptions is to surround the entire work portion of the run() method with a try{ } block that catches the InterruptedException.
15
Terminating Threads (3)
public class MyRunnable implements Runnable { public void run() { try { while (...) { do work Thread.sleep(...); } } catch (InterruptedException e) {} clean up }
16
Sensing Interruptions (1)
More robust way: sleep() and wait() occasionally, catch an exception and react to interruption sleep() and wait() check the “interrupted” flag and, if the flag is set, the methods throw InterruptedException and then the interruption status is cleared! Occasionally, when it is inconvenient to call sleep() or wait(), you should check the “interrupted” flag manually Thread.currentThread().isInterrupted() Recommendation: Terminate run() when sensing interruption
17
Sensing Interruptions (2)
public class MyRunnable implements Runnable { public void run() { try { while (...) { do work Thread.sleep(...); } } catch (InterruptedException e) {} clean up }
18
Thread Synchronization
Example Two producers, one consumer Each producer thread inserts 100 greetings into the same queue. Each consumer thread removes all of the greetings in the queue.
19
Producer Thread In the try{ } block
int i = 1; while (i <= greetingCount) { if (!queue.isFull()) { queue.add(i + ": " + greeting); i++; } Thread.sleep((int)(Math.random() * DELAY)); }
20
Consumer Thread In the try{ } block int i = 1;
while (i <= greetingCount) { if (!queue.isEmpty()) { Object greeting = queue.remove(); System.out.println(greeting); i++; } Thread.sleep((int)(Math.random() * DELAY)); }
21
Expected Program Output
1: Hello, World! 1: Goodbye, World! 2: Hello, World! 3: Hello, World! : Goodbye, World! 100: Goodbye, World!
22
Why is Output Corrupted?
Sometimes, the program will corrupt the queue and not work correctly. The consumer thread gets stuck and won’t complete. Even though 200 greetings were inserted in the queue, it can’t retrieve them all. It may complete, but print the same greetings repeatedly. Can you spot the problem? Can see problem better when turning debugging on queue.setDebug(true); Ch9/queue1/ThreadTester.java Ch9/queue1/Producer.java Ch9/queue1/Consumer.java Ch9/queue1/BoundedQueue.java
23
Race Condition Race Condition occurs if the effect of multiple threads on shared data depends on the order in which the threads are scheduled. Multiple threads, in their race to complete their respective task, rush to win the race.
24
Race Condition Scenario
First thread calls add and executes elements[tail] = anObject; First thread at end of time slice Second thread calls add and executes elements[tail] = anObject; tail++; Second thread at end of time slice First thread executes tail++;
25
Resolve a Race Condition
To fix the race conditions, you need to ensure that only one thread manipulates the queue at any given moment.
26
Locks Locking Mechanism Two kinds of locks
Thread can temporarily acquire ownership of a lock When another thread tries to acquire same lock, it is blocked. When first thread releases the lock, other threads are unblocked and try again Two kinds of locks Objects of ReentrantLock class or another class implementing java.util.concurrent.Lock interface type in java.util.concurrent.locks packageLocks Locks that are built into every Java object
27
Reentrant Locks aLock = new ReentrantLock(); . . . aLock.lock(); try
{ protected code } finally { aLock.unlock(); The finally clause ensures that the lock is unlocked even when an exception is thrown in the protected code.
28
Scenario with Locks First thread calls add and acquires lock, then executes elements[tail] = anObject; Second thread calls add and tries to acquire lock, but it is blocked First thread executes tail++; First thread completes add, releases lock Second thread unblocked Second thread acquires lock, starts executing protected code The remove() method of the queue must be protected by the same lock. After all, if one thread calls add(), we don’t want another thread to execute the remove() method on the same object.
29
Deadlocks (1) A deadlock occurs if no thread can proceed because each thread is waiting for another to do some work first. (Ex) Having a lock is still not enough to synchronize add() and remove() methods. Consider the following code. It can still be interrupted. What if the thread in interrupted right before isFull() is called in the if condition? if (!queue.isFull()) queue.add(...);
30
Deadlocks (2) Thus, the test using the if statement must move test inside add method public void add(E newValue) { queueLock.lock(); try { while (queue is full) wait for more space } finally { qeueLock.unlock(); } }
31
Deadlocks (3) Problem How can you wait for more space? You can’t simply call sleep() inside the try block. If a thread sleeps after locking queueLock, no other thread can remove elements because that block of code is protected by the same lock. The consumer thread will call remove, but it will simply be blocked until the add() method exits. But, the add method doesn’t exit until it has space available. This is called a deadlock. Deadlock vs. Live lock Precisely speaking the above situation is a “live lock”.
32
Avoiding Deadlocks (1) Use an object of a class which implements the Condition interface to manage "space available" condition private Lock queueLock = new ReentrantLock(); private Condition spaceAvailableCondition = queueLock.newCondition(); Call await() when condition is not fulfilled to add itself (the current thread) to a set of threads that are waiting for the condition and it enters a blocked state. public void add(E newValue) { while (size == elements.length) spaceAvailableCondition.await(); }
33
Avoiding Deadlocks (2) signalAll() or signal(): The signalAll() method unblocks all threads waiting for the condition, making them all runnable again. It is called whenever the state of an object has changed in a way that might benefit waiting threads. public E remove() { E r = elements[head]; spaceAvailableCondition.signalAll(); // Unblock waiting threads return r; } Ch9/queue2/BoundedQueue.java
34
Object Locks Every java object has an associated object lock.
To acquire and release the lock belonging to the implicit parameter of a method: simply tag the method with the synchronized keyword. To protect an queue object public class BoundedQueue<E> { public synchronized void add(E newValue) { } public synchronized E remove() { } }
35
Object Locks Each object lock comes with one condition object.
To wait on that condition, call wait() Object.wait() blocks current thread and adds it to wait set To signal that the condition has changed, call notifyAll() or notify() Object.notifyAll unblocks waiting threads public synchronized void add(E newValue) throws InterruptedException { while (size == elements.length) wait(); elements[tail] = anObject; notifyAll(); // notifies threads waiting to remove elements } Ch9/queue3/BoundedQueue.java
36
Visualizing Locks Object = phone booth Thread = person
Locked object = closed booth Blocked thread = person waiting for booth to open
37
Animations Use thread for the visualization of the steps of an algorithm. (Ex) Sorter Animation: Ch9/animation/Sorter.java Sleeps inside compare method Pass custom comparator Comparator<Double> comp = new Comparator<Double>() { public int compare(Double d1, Double d2) { update drawing data pause the thread //sleep() return d1.compareTo(d2); } };
38
Algorithm Animation Ch9/animation1/ArrayComponent.java
Ch9/animation1/AnimationTester.java
39
Pausing and Running the Animation
To see the result of each step in the sorting We might want to pause animation until "Run" or "Step" button is clicked. Try to use built-in thread-safe construct in java.util.concurrent Trick: Use a blocking queue What the animation does are: Button click adds string "Run" or "Step" to queue Animation thread calls the take() method on the queue, blocks if no string inserted Ch9/animation2/Sorter.java Ch9/animation2/AnimationTester.java
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.