1 <!doctype html> 2 <!-- 3 Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. 4 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 6 This code is free software; you can redistribute it and/or modify it 7 under the terms of the GNU General Public License version 2 only, as 8 published by the Free Software Foundation. Oracle designates this 9 particular file as subject to the "Classpath" exception as provided 10 by Oracle in the LICENSE file that accompanied this code. 11 12 This code is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 version 2 for more details (a copy is included in the LICENSE file that 16 accompanied this code). 17 18 You should have received a copy of the GNU General Public License version 19 2 along with this work; if not, write to the Free Software Foundation, 20 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 22 Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 or visit www.oracle.com if you need additional information or have any 24 questions. 25 --> 26 <html lang="en"> 27 <head> 28 <title>Java Thread Primitive Deprecation</title> 29 <link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style"> 30 </head> 31 <body> 32 <h2>Java Thread Primitive Deprecation</h2> 33 <hr> 34 <h3>Why is <code>Thread.stop</code> deprecated?</h3> 35 <p>Because it is inherently unsafe. Stopping a thread causes it to 36 unlock all the monitors that it has locked. (The monitors are 37 unlocked as the <code>ThreadDeath</code> exception propagates up 38 the stack.) If any of the objects previously protected by these 39 monitors were in an inconsistent state, other threads may now view 40 these objects in an inconsistent state. Such objects are said to be 41 <i>damaged</i>. When threads operate on damaged objects, arbitrary 42 behavior can result. This behavior may be subtle and difficult to 43 detect, or it may be pronounced. Unlike other unchecked exceptions, 44 <code>ThreadDeath</code> kills threads silently; thus, the user has 45 no warning that his program may be corrupted. The corruption can 46 manifest itself at any time after the actual damage occurs, even 47 hours or days in the future.</p> 48 <hr> 49 <h3>Couldn't I just catch the <code>ThreadDeath</code> exception 50 and fix the damaged object?</h3> 51 <p>In theory, perhaps, but it would <em>vastly</em> complicate the 52 task of writing correct multithreaded code. The task would be 53 nearly insurmountable for two reasons:</p> 54 <ol> 55 <li>A thread can throw a <code>ThreadDeath</code> exception 56 <i>almost anywhere</i>. All synchronized methods and blocks would 57 have to be studied in great detail, with this in mind.</li> 58 <li>A thread can throw a second <code>ThreadDeath</code> exception 59 while cleaning up from the first (in the <code>catch</code> or 60 <code>finally</code> clause). Cleanup would have to be repeated till 61 it succeeded. The code to ensure this would be quite complex.</li> 62 </ol> 63 In sum, it just isn't practical. 64 <hr> 65 <h3>What about <code>Thread.stop(Throwable)</code>?</h3> 66 <p>In addition to all of the problems noted above, this method may 67 be used to generate exceptions that its target thread is unprepared 68 to handle (including checked exceptions that the thread could not 69 possibly throw, were it not for this method). For example, the 70 following method is behaviorally identical to Java's 71 <code>throw</code> operation, but circumvents the compiler's 72 attempts to guarantee that the calling method has declared all of 73 the checked exceptions that it may throw:</p> 74 <pre> 75 static void sneakyThrow(Throwable t) { 76 Thread.currentThread().stop(t); 77 } 78 </pre> 79 <hr> 80 <h3>What should I use instead of <code>Thread.stop</code>?</h3> 81 <p>Most uses of <code>stop</code> should be replaced by code that 82 simply modifies some variable to indicate that the target thread 83 should stop running. The target thread should check this variable 84 regularly, and return from its run method in an orderly fashion if 85 the variable indicates that it is to stop running. To ensure prompt 86 communication of the stop-request, the variable must be 87 <code>volatile</code> (or access to the variable must be 88 synchronized).</p> 89 <p>For example, suppose your applet contains the following 90 <code>start</code>, <code>stop</code> and <code>run</code> 91 methods:</p> 92 <pre> 93 private Thread blinker; 94 95 public void start() { 96 blinker = new Thread(this); 97 blinker.start(); 98 } 99 100 public void stop() { 101 blinker.stop(); // UNSAFE! 102 } 103 104 public void run() { 105 while (true) { 106 try { 107 Thread.sleep(interval); 108 } catch (InterruptedException e){ 109 } 110 repaint(); 111 } 112 } 113 </pre> 114 You can avoid the use of <code>Thread.stop</code> by replacing the 115 applet's <code>stop</code> and <code>run</code> methods with: 116 <pre> 117 private volatile Thread blinker; 118 119 public void stop() { 120 blinker = null; 121 } 122 123 public void run() { 124 Thread thisThread = Thread.currentThread(); 125 while (blinker == thisThread) { 126 try { 127 Thread.sleep(interval); 128 } catch (InterruptedException e){ 129 } 130 repaint(); 131 } 132 } 133 </pre> 134 <hr> 135 <h3>How do I stop a thread that waits for long periods (e.g., for 136 input)?</h3> 137 <p>That's what the <code>Thread.interrupt</code> method is for. The 138 same "state based" signaling mechanism shown above can be used, but 139 the state change (<code>blinker = null</code>, in the previous 140 example) can be followed by a call to 141 <code>Thread.interrupt</code>, to interrupt the wait:</p> 142 <pre> 143 public void stop() { 144 Thread moribund = waiter; 145 waiter = null; 146 moribund.interrupt(); 147 } 148 </pre> 149 For this technique to work, it's critical that any method that 150 catches an interrupt exception and is not prepared to deal with it 151 immediately reasserts the exception. We say <em>reasserts</em> 152 rather than <em>rethrows</em>, because it is not always possible to 153 rethrow the exception. If the method that catches the 154 <code>InterruptedException</code> is not declared to throw this 155 (checked) exception, then it should "reinterrupt itself" with the 156 following incantation: 157 <pre> 158 Thread.currentThread().interrupt(); 159 </pre> 160 This ensures that the Thread will reraise the 161 <code>InterruptedException</code> as soon as it is able. 162 <hr> 163 <h3>What if a thread doesn't respond to 164 <code>Thread.interrupt</code>?</h3> 165 <p>In some cases, you can use application specific tricks. For 166 example, if a thread is waiting on a known socket, you can close 167 the socket to cause the thread to return immediately. 168 Unfortunately, there really isn't any technique that works in 169 general. <em>It should be noted that in all situations where a 170 waiting thread doesn't respond to <code>Thread.interrupt</code>, it 171 wouldn't respond to <code>Thread.stop</code> either.</em> Such 172 cases include deliberate denial-of-service attacks, and I/O 173 operations for which thread.stop and thread.interrupt do not work 174 properly.</p> 175 <hr> 176 <h3>Why are <code>Thread.suspend</code> and 177 <code>Thread.resume</code> deprecated?</h3> 178 <p><code>Thread.suspend</code> is inherently deadlock-prone. If the 179 target thread holds a lock on the monitor protecting a critical 180 system resource when it is suspended, no thread can access this 181 resource until the target thread is resumed. If the thread that 182 would resume the target thread attempts to lock this monitor prior 183 to calling <code>resume</code>, deadlock results. Such deadlocks 184 typically manifest themselves as "frozen" processes.</p> 185 <hr> 186 <h3>What should I use instead of <code>Thread.suspend</code> and 187 <code>Thread.resume</code>?</h3> 188 <p>As with <code>Thread.stop</code>, the prudent approach is to 189 have the "target thread" poll a variable indicating the desired 190 state of the thread (active or suspended). When the desired state 191 is suspended, the thread waits using <code>Object.wait</code>. When 192 the thread is resumed, the target thread is notified using 193 <code>Object.notify</code>.</p> 194 <p>For example, suppose your applet contains the following 195 mousePressed event handler, which toggles the state of a thread 196 called <code>blinker</code>:</p> 197 <pre> 198 private boolean threadSuspended; 199 200 Public void mousePressed(MouseEvent e) { 201 e.consume(); 202 203 if (threadSuspended) 204 blinker.resume(); 205 else 206 blinker.suspend(); // DEADLOCK-PRONE! 207 208 threadSuspended = !threadSuspended; 209 } 210 </pre> 211 You can avoid the use of <code>Thread.suspend</code> and 212 <code>Thread.resume</code> by replacing the event handler above 213 with: 214 <pre> 215 public synchronized void mousePressed(MouseEvent e) { 216 e.consume(); 217 218 threadSuspended = !threadSuspended; 219 220 if (!threadSuspended) 221 notify(); 222 } 223 </pre> 224 and adding the following code to the "run loop": 225 <pre> 226 synchronized(this) { 227 while (threadSuspended) 228 wait(); 229 } 230 </pre> 231 The <code>wait</code> method throws the 232 <code>InterruptedException</code>, so it must be inside a <code>try 233 ... catch</code> clause. It's fine to put it in the same clause as 234 the <code>sleep</code>. The check should follow (rather than 235 precede) the <code>sleep</code> so the window is immediately 236 repainted when the thread is "resumed." The resulting 237 <code>run</code> method follows: 238 <pre> 239 public void run() { 240 while (true) { 241 try { 242 Thread.sleep(interval); 243 244 synchronized(this) { 245 while (threadSuspended) 246 wait(); 247 } 248 } catch (InterruptedException e){ 249 } 250 repaint(); 251 } 252 } 253 </pre> 254 Note that the <code>notify</code> in the <code>mousePressed</code> 255 method and the <code>wait</code> in the <code>run</code> method are 256 inside <code>synchronized</code> blocks. This is required by the 257 language, and ensures that <code>wait</code> and 258 <code>notify</code> are properly serialized. In practical terms, 259 this eliminates race conditions that could cause the "suspended" 260 thread to miss a <code>notify</code> and remain suspended 261 indefinitely. 262 <p>While the cost of synchronization in Java is decreasing as the 263 platform matures, it will never be free. A simple trick can be used 264 to remove the synchronization that we've added to each iteration of 265 the "run loop." The synchronized block that was added is replaced 266 by a slightly more complex piece of code that enters a synchronized 267 block only if the thread has actually been suspended:</p> 268 <pre> 269 if (threadSuspended) { 270 synchronized(this) { 271 while (threadSuspended) 272 wait(); 273 } 274 } 275 </pre> 276 <p>In the absence of explicit synchronization, 277 <code>threadSuspended</code> must be made <code>volatile</code> to ensure 278 prompt communication of the suspend-request.</p> 279 The resulting <code>run</code> method is: 280 <pre> 281 private volatile boolean threadSuspended; 282 283 public void run() { 284 while (true) { 285 try { 286 Thread.sleep(interval); 287 288 if (threadSuspended) { 289 synchronized(this) { 290 while (threadSuspended) 291 wait(); 292 } 293 } 294 } catch (InterruptedException e){ 295 } 296 repaint(); 297 } 298 } 299 </pre> 300 <hr size="3" noshade="noshade" /> 301 <h3>Can I combine the two techniques to produce a thread that may 302 be safely "stopped" or "suspended"?</h3> 303 Yes, it's reasonably straightforward. The one subtlety is that the 304 target thread may already be suspended at the time that another 305 thread tries to stop it. If the <code>stop</code> method merely sets 306 the state variable (<code>blinker</code>) to null, the target thread 307 will remain suspended (waiting on the monitor), rather than exiting 308 gracefully as it should. If the applet is restarted, multiple 309 threads could end up waiting on the monitor at the same time, 310 resulting in erratic behavior. 311 <p>To rectify this situation, the <code>stop</code> method must ensure 312 that the target thread resumes immediately if it is suspended. Once 313 the target thread resumes, it must recognize immediately that it 314 has been stopped, and exit gracefully. Here's how the resulting 315 <code>run</code> and <code>stop</code> methods look:</p> 316 <pre> 317 public void run() { 318 Thread thisThread = Thread.currentThread(); 319 while (blinker == thisThread) { 320 try { 321 Thread.sleep(interval); 322 323 synchronized(this) { 324 while (threadSuspended && blinker==thisThread) 325 wait(); 326 } 327 } catch (InterruptedException e){ 328 } 329 repaint(); 330 } 331 } 332 333 public synchronized void stop() { 334 blinker = null; 335 notify(); 336 } 337 </pre> 338 If the <code>stop</code> method calls <code>Thread.interrupt</code>, as 339 described above, it needn't call <code>notify</code> as well, but it 340 still must be synchronized. This ensures that the target thread 341 won't miss an interrupt due to a race condition. 342 <hr> 343 <h3>What about <code>Thread.destroy</code>?</h3> 344 <code>Thread.destroy</code> was never implemented and has been 345 deprecated. If it were implemented, it would be deadlock-prone in 346 the manner of <code>Thread.suspend</code>. (In fact, it is roughly 347 equivalent to <code>Thread.suspend</code> without the possibility 348 of a subsequent <code>Thread.resume</code>.) 349 <hr> 350 <h3>Why is <code>Runtime.runFinalizersOnExit</code> 351 deprecated?</h3> 352 Because it is inherently unsafe. It may result in finalizers being 353 called on live objects while other threads are concurrently 354 manipulating those objects, resulting in erratic behavior or 355 deadlock. While this problem could be prevented if the class whose 356 objects are being finalized were coded to "defend against" this 357 call, most programmers do <i>not</i> defend against it. They assume 358 that an object is dead at the time that its finalizer is called. 359 <p>Further, the call is not "thread-safe" in the sense that it sets 360 a VM-global flag. This forces <i>every</i> class with a finalizer 361 to defend against the finalization of live objects!</p> 362 <p><!-- Body text ends here --></p> 363 </body> 364 </html>