Deadlock with a single thread in java - java

I read that a single user thread can deadlock with a system thread.
My question is , this system thread can be any thread (not necessarily a java thread) that is sharing resources with the java thread. E.g. : I/O on 2 files after taking lock on the files.
So unless the system thread shares the resource with the java thread, it can't create deadlock.
Is there any other example of the above statement in bold.
Another question:
If there are 2 functions using 2 locks, they should lock in the same order. But is it mandatory to release in the same reverse order. Can the lock release order differ for the 2 functions
E.g :
function1() {
try {
lock1.lock();
lock2.lock();
} finally {
lock2.unlock();
lock1.unlock();
}
}
function2() {
try {
lock1.lock();
lock2.lock();
} finally {
lock1.unlock();
lock2.unlock();
}
}
Link for reference : if a single user thread deadlocks, a system thread must also be involved

It's correct that a single Java thread cannot deadlock against itself if only Java object monitor locks are involved.
It's not entirely clear what you mean by "system thread". Even when running a simple program, a JVM will have several threads running, such as a finalizer thread, or for GUI applications, an event distribution thread (EDT). These threads can potentially take Java object monitor locks and therefore deadlock against a single application thread.
A single Java thread can deadlock against external processes, not other Java threads. For example, consider this program:
public static void main(String[] args) throws Exception {
Process proc = Runtime.getRuntime().exec("cat");
byte[] buffer = new byte[100_000];
OutputStream out = proc.getOutputStream();
out.write(buffer);
out.close();
InputStream in = proc.getInputStream();
int count = in.read(buffer);
System.out.println(count);
}
This runs "cat" which simply copies from stdin to stdout. This program will usually deadlock, since it writes a large amount of data to the subprocess. The subprocess will block writing to its output, since the parent hasn't read it yet. This prevents the subprocess from reading all its input. Thus the Java thread has deadlocked against the subprocess. (The usual way to deal with this situation is to have another Java thread read the subprocess output.)
A single Java thread can deadlock if it's waiting for a notification that never occurs. Consider:
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
synchronized (obj) {
obj.wait();
}
}
This program will never terminate since nothing will ever notify obj or interrupt the thread. This may seem a bit contrived, but instances of this "lost wakeup problem" do occur in practice. A system with bugs may fail to set state properly, or call notify at the wrong time, or call notify instead of notifyAll, leaving a thread blocked in a wait call awaiting a notification that will never occur. In such cases it might be hard to identify another thread that this thread is deadlocked against, since that thread might have died in the past, or it might not have been created yet. But it is surely deadlock.
UPDATE
I ran across another example of a single-threaded deadlock. Goetz et. al., Java Concurrency In Practice p. 215, describes thread-starvation deadlock. Consider an example where
a task that submits a task and waits for its result executes in a single-threaded Executor. In that case, the first task will wait forever, permanently stalling that task and all others waiting to execute in that Executor.
(A single-threaded Executor is basically a single thread processing a queue of tasks, one at a time.)
UPDATE 2
I've found another example in the literature of a single-thread deadlock:
There are three patterns of pairwise deadlock that can occur using monitors. In practice, of course, deadlocks often involve more than two processes, in which case the actual patterns observed tend to be more complicated; conversely, it is also possible for a single process to deadlock with itself (for example, if an entry procedure is recursive).
Lampson, Butler W., and David D. Redell. Experience with Processes and Monitors in Mesa. CACM Vol. 23 No. 2, Feb 1980.
Note that in this paper, a "process" refers to what we'd call a thread and an "entry procedure" is like a synchronized method. However, in Mesa, monitors are not re-entrant, so a single thread can deadlock itself if it attempts to enter the same monitor a second time.
The same is true in Posix threads. If a thread calls pthread_mutex_lock a second time on a normal (i.e., not recursive) mutex, the thread will deadlock on itself.
From these examples, I conclude that "deadlock" does not strictly require two or more threads.

For the first question: think of any Swing application. The main thread may interfere with the Event Dispatch Thread for example easily (since all the event handling takes place in that specific thread). Also, you could play around with the finalizer thread.
For the second question: yes, you can release the locks in any order.

Related

Why jdk Thread.stop()/suspend()/resume() functions are not safe and obsoleted? [duplicate]

Why is Thread.stop() deprecated in Java? On their website, I see the following:
Why is Thread.stop deprecated?
Because it is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it has locked. (The monitors are unlocked as the ThreadDeath exception propagates up the stack.) If any of the objects previously protected by these monitors were in an inconsistent state, other threads may now view these objects in an inconsistent state. Such objects are said to be damaged. When threads operate on damaged objects, arbitrary behavior can result. This behavior may be subtle and difficult to detect, or it may be pronounced. Unlike other unchecked exceptions, ThreadDeath kills threads silently; thus, the user has no warning that his program may be corrupted. The corruption can manifest itself at any time after the actual damage occurs, even hours or days in the future.
I don't understand what they mean by "monitors". Regardless, my question is if Thread.stop() should not be called then how should a Java thread be stopped?
You asked:
My question is if theres no way to stop a thread in Java then how to stop a thread?
The Answer: In Java there's no clean, quick or reliable way to stop a thread.
Thread termination is not so straight forward. A running thread, often called by many writers as a light-weight process, has its own stack and is the master of its own destiny (well daemons are). It may own files and sockets. It may hold locks. Abrupt Termination is not always easy: Unpredictable consequences may arise if the thread is in the middle of writing to a file and is killed before it can finish writing. Or what about the monitor locks held by the thread when it is shot in the head?
Instead, Threads rely on a cooperative mechanism called Interruption. This means that Threads could only signal other threads to stop, not force them to stop.
To stop threads in Java, we rely on a co-operative mechanism called Interruption. The concept is very simple. To stop a thread, all we can do is deliver it a signal, aka interrupt it, requesting that the thread stops itself at the next available opportunity. That’s all. There is no telling what the receiver thread might do with the signal: it may not even bother to check the signal; or even worse ignore it.
Source: https://codeahoy.com/java/How-To-Stop-Threads-Safely/
When your thread handles interrupts correctly, it should be possible to instantly terminate it with use of ExecutorService interface. According to Oracle documentation, ExecutorService.shutdownNow() method, attempts to stop all actively executing tasks without waiting for their termination. There are however no guarantees beyond best-effort attempts to stop them. Here is some sample code:
class MyThread implements Runnable{
#Override
public void run() {
for (int i = 1; i < 10000000; i++)
try {
System.out.println(i + " ThreadID: " + Thread.currentThread().getId());
if (Thread.interrupted())
throw new InterruptedException();
} catch (InterruptedException e) {
return;
}
}
}
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(new MyThread());
executor.submit(new MyThread());
executor.submit(new MyThread());
executor.shutdownNow();
Without termination each thread should print message to console 10000000 times. executor.shutdownNow() method instantly stops all three threads.
The right way is to use a join. Instead of prematurely stopping the execution of a thread, join will wait for the thread to finish execution before moving to the next statement.
Thread exampleThread = new Thread(){
public void run(){
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
//handle the exception
}
}
};
exampleThread.start();
exampleThread.join();
Here exampleThread.join() will wait until exampleThread is done executing before moving to the next statement. However, the onus of making sure that the thread does finish execution is on the programmer.
In essence there is no way to stop a thread but if you design it right you should not need to stop the thread.
The logic to stop the thread should be handled in your implementation of the thread, so that you are sure that everything goes the way you want.
For example, you could create a cancel() method that changes the state of the thread, which is checked cyclically. Like this:
class StoppableThread implements Runnable {
boolean isCancelled = false;
public void run() {
while (!isCancelled) {
System.out.println("Thread is running with all its might!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void cancel () {
isCancelled = true;
}
}
From https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html:
Most uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. To ensure prompt communication of the stop-request, the variable must be volatile (or access to the variable must be synchronized
).
Threads in java are interesting because how you implement them depends on the purpose of the program you are writing.
If you do not prioritize the efficiency of your program, the thread.join() is a method that's used to wait for a Java thread to "finish" executing. Note, it's used to wait for a Java thread, not to stop a thread, and in this case we can assume a thread finishes executing after it's done running the run() method.
The reason using the thread.stop() method is dangerous, is because we do not know how the scheduler has ordered the execution of the thread, and that uncertainty is quite frustrating, but we have to accept it. Let's say you use the thread.stop method while the thread is reading objects from main memory. That may cause a huge overhead because the scheduler is now forced to sort of prioritize stopping this thread, and ignore other threads...
So this is one of the many reason why using thread.stop should be discouraged

How do i stop a Thread in java, I see a line over the stop? [duplicate]

Why is Thread.stop() deprecated in Java? On their website, I see the following:
Why is Thread.stop deprecated?
Because it is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it has locked. (The monitors are unlocked as the ThreadDeath exception propagates up the stack.) If any of the objects previously protected by these monitors were in an inconsistent state, other threads may now view these objects in an inconsistent state. Such objects are said to be damaged. When threads operate on damaged objects, arbitrary behavior can result. This behavior may be subtle and difficult to detect, or it may be pronounced. Unlike other unchecked exceptions, ThreadDeath kills threads silently; thus, the user has no warning that his program may be corrupted. The corruption can manifest itself at any time after the actual damage occurs, even hours or days in the future.
I don't understand what they mean by "monitors". Regardless, my question is if Thread.stop() should not be called then how should a Java thread be stopped?
You asked:
My question is if theres no way to stop a thread in Java then how to stop a thread?
The Answer: In Java there's no clean, quick or reliable way to stop a thread.
Thread termination is not so straight forward. A running thread, often called by many writers as a light-weight process, has its own stack and is the master of its own destiny (well daemons are). It may own files and sockets. It may hold locks. Abrupt Termination is not always easy: Unpredictable consequences may arise if the thread is in the middle of writing to a file and is killed before it can finish writing. Or what about the monitor locks held by the thread when it is shot in the head?
Instead, Threads rely on a cooperative mechanism called Interruption. This means that Threads could only signal other threads to stop, not force them to stop.
To stop threads in Java, we rely on a co-operative mechanism called Interruption. The concept is very simple. To stop a thread, all we can do is deliver it a signal, aka interrupt it, requesting that the thread stops itself at the next available opportunity. That’s all. There is no telling what the receiver thread might do with the signal: it may not even bother to check the signal; or even worse ignore it.
Source: https://codeahoy.com/java/How-To-Stop-Threads-Safely/
When your thread handles interrupts correctly, it should be possible to instantly terminate it with use of ExecutorService interface. According to Oracle documentation, ExecutorService.shutdownNow() method, attempts to stop all actively executing tasks without waiting for their termination. There are however no guarantees beyond best-effort attempts to stop them. Here is some sample code:
class MyThread implements Runnable{
#Override
public void run() {
for (int i = 1; i < 10000000; i++)
try {
System.out.println(i + " ThreadID: " + Thread.currentThread().getId());
if (Thread.interrupted())
throw new InterruptedException();
} catch (InterruptedException e) {
return;
}
}
}
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(new MyThread());
executor.submit(new MyThread());
executor.submit(new MyThread());
executor.shutdownNow();
Without termination each thread should print message to console 10000000 times. executor.shutdownNow() method instantly stops all three threads.
The right way is to use a join. Instead of prematurely stopping the execution of a thread, join will wait for the thread to finish execution before moving to the next statement.
Thread exampleThread = new Thread(){
public void run(){
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
//handle the exception
}
}
};
exampleThread.start();
exampleThread.join();
Here exampleThread.join() will wait until exampleThread is done executing before moving to the next statement. However, the onus of making sure that the thread does finish execution is on the programmer.
In essence there is no way to stop a thread but if you design it right you should not need to stop the thread.
The logic to stop the thread should be handled in your implementation of the thread, so that you are sure that everything goes the way you want.
For example, you could create a cancel() method that changes the state of the thread, which is checked cyclically. Like this:
class StoppableThread implements Runnable {
boolean isCancelled = false;
public void run() {
while (!isCancelled) {
System.out.println("Thread is running with all its might!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void cancel () {
isCancelled = true;
}
}
From https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html:
Most uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. To ensure prompt communication of the stop-request, the variable must be volatile (or access to the variable must be synchronized
).
Threads in java are interesting because how you implement them depends on the purpose of the program you are writing.
If you do not prioritize the efficiency of your program, the thread.join() is a method that's used to wait for a Java thread to "finish" executing. Note, it's used to wait for a Java thread, not to stop a thread, and in this case we can assume a thread finishes executing after it's done running the run() method.
The reason using the thread.stop() method is dangerous, is because we do not know how the scheduler has ordered the execution of the thread, and that uncertainty is quite frustrating, but we have to accept it. Let's say you use the thread.stop method while the thread is reading objects from main memory. That may cause a huge overhead because the scheduler is now forced to sort of prioritize stopping this thread, and ignore other threads...
So this is one of the many reason why using thread.stop should be discouraged

Thread.stop() - deprecated

Why is Thread.stop() deprecated in Java? On their website, I see the following:
Why is Thread.stop deprecated?
Because it is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it has locked. (The monitors are unlocked as the ThreadDeath exception propagates up the stack.) If any of the objects previously protected by these monitors were in an inconsistent state, other threads may now view these objects in an inconsistent state. Such objects are said to be damaged. When threads operate on damaged objects, arbitrary behavior can result. This behavior may be subtle and difficult to detect, or it may be pronounced. Unlike other unchecked exceptions, ThreadDeath kills threads silently; thus, the user has no warning that his program may be corrupted. The corruption can manifest itself at any time after the actual damage occurs, even hours or days in the future.
I don't understand what they mean by "monitors". Regardless, my question is if Thread.stop() should not be called then how should a Java thread be stopped?
You asked:
My question is if theres no way to stop a thread in Java then how to stop a thread?
The Answer: In Java there's no clean, quick or reliable way to stop a thread.
Thread termination is not so straight forward. A running thread, often called by many writers as a light-weight process, has its own stack and is the master of its own destiny (well daemons are). It may own files and sockets. It may hold locks. Abrupt Termination is not always easy: Unpredictable consequences may arise if the thread is in the middle of writing to a file and is killed before it can finish writing. Or what about the monitor locks held by the thread when it is shot in the head?
Instead, Threads rely on a cooperative mechanism called Interruption. This means that Threads could only signal other threads to stop, not force them to stop.
To stop threads in Java, we rely on a co-operative mechanism called Interruption. The concept is very simple. To stop a thread, all we can do is deliver it a signal, aka interrupt it, requesting that the thread stops itself at the next available opportunity. That’s all. There is no telling what the receiver thread might do with the signal: it may not even bother to check the signal; or even worse ignore it.
Source: https://codeahoy.com/java/How-To-Stop-Threads-Safely/
When your thread handles interrupts correctly, it should be possible to instantly terminate it with use of ExecutorService interface. According to Oracle documentation, ExecutorService.shutdownNow() method, attempts to stop all actively executing tasks without waiting for their termination. There are however no guarantees beyond best-effort attempts to stop them. Here is some sample code:
class MyThread implements Runnable{
#Override
public void run() {
for (int i = 1; i < 10000000; i++)
try {
System.out.println(i + " ThreadID: " + Thread.currentThread().getId());
if (Thread.interrupted())
throw new InterruptedException();
} catch (InterruptedException e) {
return;
}
}
}
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(new MyThread());
executor.submit(new MyThread());
executor.submit(new MyThread());
executor.shutdownNow();
Without termination each thread should print message to console 10000000 times. executor.shutdownNow() method instantly stops all three threads.
The right way is to use a join. Instead of prematurely stopping the execution of a thread, join will wait for the thread to finish execution before moving to the next statement.
Thread exampleThread = new Thread(){
public void run(){
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
//handle the exception
}
}
};
exampleThread.start();
exampleThread.join();
Here exampleThread.join() will wait until exampleThread is done executing before moving to the next statement. However, the onus of making sure that the thread does finish execution is on the programmer.
In essence there is no way to stop a thread but if you design it right you should not need to stop the thread.
The logic to stop the thread should be handled in your implementation of the thread, so that you are sure that everything goes the way you want.
For example, you could create a cancel() method that changes the state of the thread, which is checked cyclically. Like this:
class StoppableThread implements Runnable {
boolean isCancelled = false;
public void run() {
while (!isCancelled) {
System.out.println("Thread is running with all its might!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void cancel () {
isCancelled = true;
}
}
From https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html:
Most uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. To ensure prompt communication of the stop-request, the variable must be volatile (or access to the variable must be synchronized
).
Threads in java are interesting because how you implement them depends on the purpose of the program you are writing.
If you do not prioritize the efficiency of your program, the thread.join() is a method that's used to wait for a Java thread to "finish" executing. Note, it's used to wait for a Java thread, not to stop a thread, and in this case we can assume a thread finishes executing after it's done running the run() method.
The reason using the thread.stop() method is dangerous, is because we do not know how the scheduler has ordered the execution of the thread, and that uncertainty is quite frustrating, but we have to accept it. Let's say you use the thread.stop method while the thread is reading objects from main memory. That may cause a huge overhead because the scheduler is now forced to sort of prioritize stopping this thread, and ignore other threads...
So this is one of the many reason why using thread.stop should be discouraged

Killing a thread with a complex subroutine. Java

As many others I have a problem killing my thread without using stop().
I have tried to use volatile on a variable with a while loop in my threads run() routine.
The problem is as far as I can see, that the while loop only checks the variable before every turn. The complex routine Im running takes a long time, and because of that the thread is not terminated immediately.
The thread I want to terminate is a routine that connects to another server and it uses a looooong time. And I want to have an abort button for this. (Terminating the thread). I'll try to explane with some code.
class MyConnectClass{
Thread conThread;
volitile boolean threadTerminator = false;
..some code with connect and abort button..
public void actionPerformed(ActionEvent e) {
String btnName = e.getActionCommand();
if(btnName.equalsIgnoreCase("terminate")){
threadTerminator = true;
conThread.interrupt();
System.out.println("#INFO# USER ABORTED CURRENT OPERATION!");
}else if(btnName.equalsIgnoreCase("connectToServer")){
conThread = new Thread() {
public void run() {
while(threadTerminator == false){
doComplexConnect(); //Uses a loooong time
}
}
}
conThread.start();
}
}
}
How can I kill my "connection" thread instantly?
Thanks.
Java abandoned the stop() approach in Threads a while back because killing a Thread ungracefully caused huge problems in the JVM. From the Javadoc for stop():
Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait.
In most cases, it is up to you to check the threadTerminator var whenever it is safe for you to terminate, and handle the thread exit gracefully. See http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
If you are doing long I/O, you may be in trouble. Some I/O operations throw an InterruptedException, in which case, you can interrupt the thread, and, if you were in that I/O, that exception will be thrown more or less instantly, and you can abort and cleanup the thread. For this reason, interrupting a thread is preferable to using a special custom threadTerminator variable - it's much more standard. In you main code outside of the I/O, check for interrupted() or isInterrupted() periodically (instead of threadTerminator == false).
If you are doing I/O that doesn't throw InterruptedException, sometimes you can close the Socket or similar, and catch the IOException. And sometimes you are stuck.
Why don't you interrupt the thread and just move on, letting it hang until it finishes? The user could initiate a different action (thread) while the old thread finishes gracefully (which, from what I see you are pretty much doing already btw)
The downside of this that you have trouble when the user starts clicking "connectToServer" a lot (many threads), or when the threads fail to terminate (hanged threads). But maybe it's sufficient for your purpose?
Edit:
It would be simple to implement a mechanism that prevents spawning a new conthread unless "it's good to go" (e.g., use a semaphore).
The tricky part will be deciding whether it's good to open a new connection. You could ask the original thread (I.e. have a isalive() method), or the party you are trying to connect to. Or you could go for a timeout solution. For example, you could let conthread update a timestamp and decide it's dead if the timestamp isn't updated for 1 min etc. The most generally applicable solution would probably be the timeout solution.

Is Sun's Thread.join method broken because it synchronizes usng the Thread object?

By both running test programs and looking at source code, it is clear that the method, as implemented by Sun, does not simply yield time to the specified thread, but actually it first attempts to obtain a monitor on the thread object. Specifically, the method is implemented as "synchronized."
Note that the wait and notify methods also require the monitor, but unlike join, it is the caller's responsibility to obtain the monitor before making the call, and the documentation clearly says so. The fact that join depends on the monitor is not documented in the Javadocs, although perhaps it is natural to make the inference.
Is the documentation clear enough?
Additionally, if the thread can't obtain the monitor for some reason, it will hang, maybe forever. While waiting for the monitor, a thread is not interruptible, and will not throw the InterruptedException as described in the documentation. On the other hand, it is not clear why a thread wouldn't be able to obtain the monitor except in the case of a programming error.
Is it reasonable to worry about contention over the monitor?
Finally, it seems inappropriate to make the operation of a timeout dependent on obtaining a monitor, unless it can be guaranteed that the task of obtaining the monitor will itself time out.
Is depending on the monitor for join() a reasonable implementation? Is it even possible to implement it any other way?
Thread.join calls wait, which releases the monitor. As this means a "joining" thread doesn't block any other thread from calling join as well, I suspect this answers most of your other queries. It doesn't prevent another caller from synchronizing on the thread's monitor (oh the joys of public monitors) but it means that the common case works fine.
Just to demonstrate that your first point is wrong, here's an example which creates 10 threads which each wait on the main thread for 5 seconds. (Please ignore the horrible exception swallowing and abuse of Date. It's only intended to be used to study the threading behaviour.)
import java.util.*;
public class Test
{
public static void main(String[] args) throws Exception
{
for (int i=0; i < 10; i++)
{
new Thread(new ThreadJoiner(Thread.currentThread(), i))
.start();
}
try
{
Thread.sleep(10000);
}
catch (InterruptedException e) {}
}
private static class ThreadJoiner implements Runnable
{
private final Thread threadToJoin;
int id;
public ThreadJoiner(Thread threadToJoin, int id)
{
this.threadToJoin = threadToJoin;
this.id = id;
}
public void run()
{
try
{
System.out.println("Thread " + id +
" waiting at " + new Date());
threadToJoin.join(5000);
System.out.println("Thread " + id +
" finished waiting at " + new Date());
}
catch (InterruptedException e) {}
}
}
}
If you run that, you'll see that all the threads start and end their waits virtually simultaneously. You don't get the ends "staggered" as you would if your concerns were well-founded.
it is clear that the method, as implemented by Sun, does not simply yield time to the specified thread, but actually it first attempts to obtain a monitor on the thread object.
It doesn't yield to the thread joined, it just waits with the assumption that at some point the thread will run to completion. Having a join() on a thread does not make it more likely to run than any other thread ready to run.
If N threads all attempt to join the same thread, and they all specify the same timeout T, then one of the threads will end up waiting at least N*T ms. In other words, each thread has to "wait its turn" to execute its wait. Is it reasonable for separate threads to execute joins serially instead of in parallel?
Threads are designed to work concurrently. If they all wait, they do so concurrently. A waiting thread does not make another thread wait longer.
.2. It is possible that a thread which enters a join with a nonzero timeout may never return.
not unless you intend this to happen.
This is because there is no guarantee the monitor will ever become available.
The situation you suggest could only occur if a thread obtains a lock on the thread and then holds it forever without waiting. This is a programming bug. IMHO You should never obtain a lock on a thread object directly.
If a thread obtains its own monitor before blocking on an I/O operation, and that operation hangs, then any thread which attempts to join the thread will also hang.
Java doesn't protect you from malicious code in your own JVM.
Is it reasonable for an operation with an explicit time out to hang indefinitely?
If it is being locked out indefinitely, yes.
.3. In order to write a correct program which uses the method, the caller must know in advance whether the target thread or some other thread could be holding the monitor.
Don't ever lock the thread object, there is no reason you should need to, and you won't have this problem. If you want to start looking at every way you could confuse other developers or yourself, then Threads isn't the place you would start IMHO.
For example, consider what happens if thread 1 is performing some sort of processing work, then thread 2 joins thread 1 with a timeout of 0, and then thread 3 attempts to join thread 1 with a timeout of 10 ms. The 0 timeout join means that thread 2 will wait until thread 1 exits. But thread 3 cannot begin its wait until thread 2 releases the monitor,
Thread 2 releases the monitor as soon as wait is called. It cannot wait and hold the monitor at the same time.
so effectively thread 3's wait of 10 ms was silently converted to an indefinite wait, which was not what the caller intended.
no. see previous comments.
Doesn't requiring the caller to know details about the implementation violate the principle of encapsulation?
It would.
.4. If a thread is blocked because it cannot obtain the monitor, it is not interruptible, and will not throw the InterruptedException as described in the documentation. So not only might a thread wait longer than expected, or even indefinitely, it may become completely unresponsive, causing the entire program to hang. Is it reasonable for an interruptible operation to become unresponsive?
yes. But this is a very rare condition. If you use the code as written, the situation you refer to will only exist for a few milli-seconds at most.
Overall, it seems inappropriate to make the operation of a timeout dependent on obtaining a monitor, unless it can be guaranteed that the task of obtaining the monitor will itself time out. Is thread join broken?
You can do what you suggest with the more recent Java 5 concurrency libraries.
However, I suggest you shouldn't assume that timeouts are guaranteed to be milli-second accurate. currentTimeMillis() used by this method is only accurate to about 16 ms on Windows XP and wait/sleep is typically 2 ms longer than it should be for small timeouts on Linux.
IMHO If you need accuracy of more than 40 ms you may have difficulty, however if you work around this you will find this doesn't have to be a problem.

Categories