2

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

S Kr
  • 1,831
  • 2
  • 25
  • 50

2 Answers2

3

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.

Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
  • It's certainly a lock-up, but whether it's "deadlock" depends somewhat on terminology. I would think it helpful to distinguish between the general case of waiting forever for an event which nobody anywhere has any desire to trigger, versus having two threads, each of which wants to let the other proceed and is waiting for an opportunity to do so. – supercat Dec 11 '13 at 01:12
  • Right, depends on terminology. Some people like to be precise about "deadlock" claiming that it requires two or more threads. In general I think "deadlock" describes a broader range of liveness problems. I've added another example that I found involving just a single thread. – Stuart Marks Dec 11 '13 at 06:40
  • That's a better example. The key aspect of deadlock is that it involves two entities of some sort waiting for each other, but they need not be threads. In a lab with two computers, each with an operator that shuffles tapes between computers and a storage cabinet, one could have deadlock if each computer had a tape loaded and was in the process of writing it, and the other computer needed information which was stored earlier on that tape (in some systems it would not be possible to unmount a tape and then remount it in such fashion as to append to the partially-written file). – supercat Dec 11 '13 at 07:13
  • There is also the trivial case in which you try to perform a join operation on a single thread i.e. `Thread.currentThread.join()` – Abel Garcia Jan 25 '16 at 11:25
1

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.

rlegendi
  • 10,466
  • 3
  • 38
  • 50
  • what if the system thread is not necessarily a java thread. Thanks in advance – S Kr Dec 07 '13 at 15:09
  • I don't think you can get into deadlock that way, the File API usually throws an exception if you cannot create OS locks for a file ([see here](http://stackoverflow.com/questions/4025721/java-file-locking)). OTOH you can get into livelocks by communicating with other processes through sockets for example. – rlegendi Dec 07 '13 at 15:41
  • I read in the "Java Threads" by scott oaks & henry wong, about it. Please check the link i have just added in the question – S Kr Dec 07 '13 at 16:17
  • 1
    Yes, that's true but only for locking-related deadlocks (that's because the reentrant nature of the locks in Java). As Stuart Marks pointed out below, if you simply go to wait there are no threads that going to notify you. – rlegendi Dec 08 '13 at 16:53