良好基础的 Java 开发人员中的 Java 死锁示例

标签 java concurrency

没看懂《接地气的java开发者》书中的死锁例子。怎么会出现这种僵局呢?

At first glance, this code looks sensible. You have two updates being sent to separate threads, each of which has to be confirmed on backup threads. This doesn’t seem too outlandish a design—if one thread has a failure, there is another thread that can potentially carry on. If you run the code, you’ll normally see an example of a deadlock—both threads will report receiving the update, but neither will confirm receiving the update for which they’re the backup thread. The reason for this is that each thread requires the other to release the lock it holds before the confirmation method can progress.

下面来自 list 4.2 一个死锁示例

public class MicroBlogNode implements SimpleMicroBlogNode {
private final String ident;

public MicroBlogNode(String ident_) {
    ident = ident_;
}

public String getIdent() {
    return ident;
}

public synchronized void propagateUpdate(Update upd_, MicroBlogNode
        backup_) {
    System.out.println(ident + ": recvd: " + upd_.getUpdateText()  + " ; backup: " + backup_.getIdent());
    backup_.confirmUpdate(this, upd_);
}

public synchronized void confirmUpdate(MicroBlogNode other_, Update
        update_) {
    System.out.println(ident + ": recvd confirm: " + update_.getUpdateText() + " from " + other_.getIdent()k);
}

public static void main(String[] args) {
    final MicroBlogNode local = new MicroBlogNode("localhost:8888");
    final MicroBlogNode other = new MicroBlogNode("localhost:8988");
    final Update first = getUpdate("1");
    final Update second = getUpdate("2");

    new Thread(new Runnable() {
        public void run() {
            local.propagateUpdate(first, other);
        }
    }).start();

    new Thread(new Runnable() {
        public void run() {
            other.propagateUpdate(second, local);
        }
    }).start();
}

最佳答案

第一个线程启动,local.propagateUpdate 被调用,并且 local 现在被锁定,因为该方法是同步的。

几乎同时,第二个线程启动,other.propagateUpdate 被调用,并且实例 other 也因同样的原因被锁定。

两个线程都愉快地打印文本。在第一个线程中,local 实例尝试通过在 other 实例上调用 confirmUpdate 来与其他线程进行确认,但是 other 仍被第二个线程锁定 - 该方法尚未返回。

在第二个线程中,other 实例尝试在 local 实例上调用 confirmUpdate,但该实例也被锁定 - 这次通过第一个线程。

localother 都在等待对方释放它们的锁,并且永远无法解决问题:这是死锁。

关于良好基础的 Java 开发人员中的 Java 死锁示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51623230/

相关文章:

c - 哪些绿色线程库可用于 C,可以匹配 Haskell 绿色线程的性能和易用性?

hibernate - JPA merge() 最佳实践

java - 变量的 volatile 写入是否可以避免乱序写入?

java - ConcurrentBitSet 中的竞争条件

带有 CSS 的 JavaFX TextArea 样式

java - 如何更改 JTabbedPane 的背景颜色?

java - 无法在 spring 应用程序中更改语言

python - Django中的并发疑惑

java - get 在没有 Activity 事务的情况下无效 - hibernate 5

java - 永远不会在相应的 try 语句的主体中抛出异常