The answer is that it depends on the kind of lock or locking mechanism.
For reentrant locks, you need two or more threads. (Note that Java primitive locks / mutexes are reentrant).
For non-reentrant lock, a single thread can deadlock itself by attempting to acquire a lock that it already holds1.
It is also possible for a thread to block itself in other ways that is practically indistinguishable from a deadlock2. For example:
Thread.currentThread().join();
will block a thread by getting it to wait until it finishes. Under the hood, the join()
call is waiting for a notification / condition that can never occur. You can do the same thing yourself explicitly; e.g.
Object lock = new Object(); // local variable
synchronized (lock) {
lock.wait();
}
1 - This depends on the precise semantics of the lock. For example, a non-reentrant lock could be implemented to throw an exception rather than deadlocking in this scenario.
2 - Whether this is actually a deadlock depends on the precise definition you use for the term "deadlock". It is inadvisable to get into arguments about terminology in a job interview!