More Multithreaded Programming in Java David Meredith Aalborg University
Sources Chapter 14 of The Java Programming Language (Fourth Edition) by Ken Arnold, James Gosling and David Holmes (Addison- Wesley, 2006) Sun Java Tutorial on Concurrency oncurrency/
Synchronized methods and statements The two code fragments to the right are equivalent In both cases, the object referenced by this is locked while doThis() and doThat() are carried out Remember that this refers to the object on which the method is called public synchronized void myMethod() { doThis(); doThat(); } public void myMethod() { synchronized(this) { doThis(); doThat(); }
Client-side and server-side synchronization Server-side synchronization is where object to be locked takes responsibility for synchronizing code that uses it – often by using a synchronized method Client-side synchronization is where responsibility for synchronizing critical regions of code lies with the code that uses the object to be locked – Means every client has to agree to use synchronized code – Less safe than server-side synchronization – Often done using synchronized statements
Synchronized statements vs. synchronized methods Synchronized statement can protect code region smaller than a whole method Synchronized statement can lock an object other than the one whose method contains the code being protected Allows for holding a lock for as short a time as possible (increases performance) Allows for increasing concurrency by using a finer granularity of locking
Interrupts If b is a Thread, then we interrupt b (“send an interrupt request to b”) by using the message b.interrupt(); If Thread b frequently calls methods that throw InterruptedException (e.g., Thread.sleep()), then the first occurrence of such a method after the interrupt is received will throw an InterruptedException – In this case, we define how the Thread responds to the interrupt in a catch clause (see PingPongRunnable.java) – Usually the run() method will be made to return
Manually responding to an interrupt Sometimes a run() method might not contain any call to a method that throws an InterruptedException In this case, need to regularly check whether the Thread has received an interrupt Using a try-catch clause allows you to centralize the interrupt handling code in one place and separate it clearly from the run code public void run() { for (int i = 0; i < 300; i++) { doSomeCalc(i); if (Thread.interrupted()) { return; } public void run() { for (int i = 0; i < 300; i++) { doSomeCalc(i); if (Thread.interrupted()) { return; } public void run() { try { for (int i = 0; i < 300; i++) { doSomeCalc(i); if (Thread.interrupted()) { throw new InterruptedException(); } } catch (InterruptedException e) { doSomeStuff(); return; } public void run() { try { for (int i = 0; i < 300; i++) { doSomeCalc(i); if (Thread.interrupted()) { throw new InterruptedException(); } } catch (InterruptedException e) { doSomeStuff(); return; }
Interrupt status flag Message, a.interrupt() causes interrupt status flag to be set to true for Thread a If a checks for interrupt status by calling static method, Thread.interrupted(), then interrupt status flag set to false (“cleared”) – Thread a ceases to be in an interrupted state If Thread b wants to know if Thread a has been interrupted, then call a.isInterrupted() from inside b – Does not clear interrupt status flag – That is, if Thread a has been interrupted, it remains in an interrupted state, as indicated by the true value of the interrupt status flag When InterruptedException thrown, interrupt status flag is cleared (i.e., set to false) – thread ceases to be in an interrupted state
The join method The call, t.join(),causes the current Thread to block (i.e., stop doing anything) until Thread t has stopped running The join method throws an InterruptedException if the current Thread is interrupted while it is waiting for another Thread to complete See HrOgFruJensen2.java
SimpleThreads.java
Guarded Blocks A guarded block suspends the current thread until another thread makes some condition become true, which restarts the current thread guardedJoy() method must not execute its last line until the shared variable joy has been made true by some other thread The while loop is keeping the processor busy while it is waiting (busy waiting) – DON’T DO THIS! public void guardedJoy() { while (!joy) {} System.out.println(“Joy has been achieved!”); }
Guarded blocks using wait and notifyAll AchievingJoy.java