我读到过单线程Java程序可能会发生死锁的情况。我很好奇是怎么回事,毕竟没有竞争。据我所记,书籍中都是用多个线程来举例说明的。如果可以,请给出一个单线程死锁的例子。
关键是你如何定义“死锁”。
例如,以下情况相当现实:单线程应用程序使用大小限制的队列,当达到限制时会阻塞。只要没有达到限制,单线程就可以正常工作。但是当达到限制时,线程将永远等待(不存在的)其他线程从队列中取出某些内容,以便它可以继续执行。
doSomething();
yield(); // may switch to another thread
doSomethingElse();
thread2的代码:
doSomething2();
yield(); // may switch to another thread
doSomethingElse2();
这被称为协作式多线程 - 所有的工作都由一个线程完成,因此在Windows 3.1中进行了多线程处理。
今天的多线程称为抢占式多线程,它只是对协作式多线程的轻微修改,其中yield()会自动定期调用。
所有这些可能归结为以下交错:
doSomething();
doSomething2();
doSomethingElse2();
doSomethingElse();
doSomething();
doSomething2();
doSomethingElse();
doSomethingElse2();
queue.put(x);
yield();
线程2:
x = queue.waitAndGet()
yield();
这个交错方式是可以的:
queue.put(x);
x = queue.waitAndGet()
但是在这里我们遇到了死锁:
x = queue.waitAndGet()
queue.put(x);
是的,单线程程序也可能出现死锁。
我敢说是的
如果您在同一线程中连续尝试获取相同的锁,则取决于锁或锁定实现的类型,它是否检查该锁是否由同一线程获取。如果实现不检查此项,则会出现死锁。
对于synchronized,这是被检查的,但我找不到Semaphore的保证。
如果您使用其他类型的锁,则必须检查规范以了解其保证的行为!
另外,正如已经指出的那样,通过读取/写入受限缓冲区,您可能会被阻塞(这与死锁不同)。例如,您将内容写入分槽缓冲区,并仅在某些条件下从中读取。当您无法再插入时,您将等待直到有一个空闲的插槽,但由于您自己进行了读取,因此这种情况永远不会发生。
所以我敢说答案应该是肯定的,尽管不那么容易并且通常更容易检测。
希望能帮到您
Mario
QED. -pbr
不。
死锁是多个线程(或进程)试图以无法继续的方式获取锁而导致的结果。
考虑一下维基百科文章中的一句话:(http://en.wikipedia.org/wiki/Deadlock)
“当两列火车在交叉口相遇时,两者都必须完全停止,直到另一个离开为止。”
不,对我来说听起来相当不可能。
但是你可以在另一个应用程序锁定你要请求的资源时理论上锁定系统资源,而该应用程序将请求你已经锁定的资源。 砰 死锁。
但操作系统应该能够通过检测并将两个资源同时分配给一个应用程序来解决这个问题。这种情况发生的机会微乎其微,但任何好的操作系统都应该能够处理这一千万分之一的机会。
如果您仔细设计并一次只锁定一个资源,则不会发生这种情况。
这其实很简单:
BlockingQueue bq = new ArrayBlockingQueue(1);
bq.take();
会死锁。
while(true){}
就是一个死锁。 - Bozhowhile (true)
与此无关。 - user207421