单线程java程序中的死锁

时间:2010-10-14 07:02:18

标签: java deadlock

读取死锁可能发生在单线程java程序中。我想知道毕竟不会有任何竞争。据我所知,书籍说明了多个主题的例子。如果单个帖子可以发生,你能举个例子吗?

7 个答案:

答案 0 :(得分:6)

这是你如何定义“死锁”的问题。

例如,这种情况有点现实:使用大小限制队列的单线程应用程序在达到其限制时阻塞。只要没有达到限制,这将适用于单个线程。但是当达到限制时,线程将永远等待(不存在的)其他线程从队列中取出某些东西,以便它可以继续。

答案 1 :(得分:2)

在多核处理器变得便宜之前,所有台式计算机都有单核处理器。单核处理器仅在线程上运行。那么多线程是如何工作的呢? Java最简单的实现是:

thread1的代码:

 doSomething();
 yield();    // may switch to another thread
 doSomethingElse();

thread2的代码:

 doSomething2();
 yield();    // may switch to another thread
 doSomethingElse2();

这称为协作多线程 - 所有这些都只需要1个线程完成,因此多线程在Windows 3.1中完成。

今天称为抢占式多线程的多线程只是对协同多线程的一个小修改,其中不时会自动调用yield()。

所有这些可能会减少到以下的交错:

doSomething();
doSomething2();
doSomethingElse2();
doSomethingElse();

或:

doSomething();
doSomething2();
doSomethingElse();
doSomethingElse2();

依此类推......我们将多线程代码转换为单线程代码。所以是的,如果在单线程中的多线程程序中也可能出现死锁。例如:

线程1:

queue.put(x);
yield();

线程2:

x = queue.waitAndGet()
yield();

这个隔行扫描没关系:

queue.put(x);
x = queue.waitAndGet()

但是我们陷入僵局:

x = queue.waitAndGet()
queue.put(x);

所以是的,单线程程序中可能存在死锁。

答案 2 :(得分:1)

我敢说是的

如果您尝试连续在同一个线程中获取相同的锁,则它取决于锁定或锁定实现的类型,是否检查锁是否由同一线程获取。如果实现没有检查这一点,则会出现死锁。

对于同步,这已经过检查,但我找不到信号量的保证。

如果你使用其他类型的锁,你必须检查规格,以确保其行为如何!

正如已经指出的那样,您可以通过读/写限制缓冲区来阻止(与死锁不同)。例如,您将事物写入时隙缓冲区,并且只在某些条件下从中读取。当你无法再插入时,你要等到一个插槽空闲,这是不会发生的,因为你自己做了阅读。

所以我敢说答案应该是肯定的,尽管不是那么容易,而且通常更容易被发现。

HTH

马里奥

答案 3 :(得分:1)

即使你的java东西是单线程的,仍然有信号处理程序,它们在与主线程不同的线程/上下文中执行。

因此,如果/当java在linux上运行时,即使在单线程解决方案上也会发生死锁。

QED。 -pbr

答案 4 :(得分:0)

没有

死锁是多个线程(或进程)尝试获取锁定的结果,两者都无法继续。

考虑维基百科文章的引用:(http://en.wikipedia.org/wiki/Deadlock

“当两列火车在一个十字路口相互接近时,两个火车都会完全停下来,直到另一列火车离开时才会再次启动。”

答案 5 :(得分:0)

不,对我来说听起来很不可能。

但理论上你可以锁定一个系统资源,而另一个应用程序锁定你要请求的另一个应用程序,该应用程序将请求你已经锁定的那个。 爆炸死锁。

但操作系统应该能够通过检测并将这两种资源分配给一个应用程序来解决这个问题。这种情况发生的可能性很小,但任何好的操作系统都应该能够处理这十亿分之一的机会。

如果您仔细进行设计并且一次只锁定一个资源,则不会发生这种情况。

答案 6 :(得分:-1)

实际上很容易:

BlockingQueue bq = new ArrayBlockingQueue(1);
bq.take();

将陷入僵局。