gpt4 book ai didi

java - 阻塞方法引起的死锁

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:41:01 24 4
gpt4 key购买 nike

假设我们创建了一个运行同步方法的线程。此方法尝试从空阻塞队列中take()。现在让一个单独的线程尝试将 put() 和元素放入阻塞队列,同时在同一对象上同步。

这会导致死锁:

  • 第一个线程不会释放锁,直到一个元素被添加到队列中。
  • 第二个线程不能添加元素,直到锁空闲以供它获取。

如果这两个操作需要是原子的并且在不同的线程上运行,如何在不导致死锁的情况下实现?

我知道 take()put() 是线程安全的。我的问题是何时将它们用作必须是原子的更大操作的一部分。

例子:

import java.util.concurrent.*;

public class DeadlockTest {

String input = "Nothing added yet!";
LinkedBlockingQueue<String> buffer = new LinkedBlockingQueue<>();

public synchronized String getFromBuffer() {
System.out.println("Trying to get input from buffer.");
try {
input = buffer.take();
} catch (InterruptedException ex) {}
System.out.println("Got:" + input + "\n");
return input;
}

public static void main(String[] args) throws InterruptedException {
DeadlockTest dl = new DeadlockTest();

new Thread(() -> {
dl.getFromBuffer();
}).start();

// Give new thread time to run.
Thread.sleep(500);

synchronized (dl) {
String message = "Hello, world!";

System.out.println("Adding: " + message);
dl.buffer.put(message);
System.out.println("Added!\n");

System.out.println("Message: " + dl.input);
}
}
}

最佳答案

Say we create a thread which runs a synchronized method. This method tries to take() from an empty blocking queue.

听起来设计很糟糕。从 synchronized 方法或 synchronized 语句中调用任何阻塞方法通常是错误的。

If the two actions need to be atomic and run on separate threads, how can this be achieved without causing a deadlock?

嗯,有两种可能性:

在一种情况下,两个线程正在处理不同的数据。在那种情况下,他们应该使用不同的锁,并且他们根本不会相互干扰。

在另一种情况下,两个线程正在处理相同的数据。在那种情况下,它们应该锁定同一个锁,并且一个线程将不得不等待另一个。


也许您误解了阻塞队列的工作原理。如果一个线程正在等待从阻塞队列中take() 某些东西,那永远不会阻止另一个线程调用put()。这与您想要的完全相反。

您想要的(以及您将从 Java 标准库中的任何阻塞队列实现中获得的)是第二个线程中的 put() 操作将唤醒正在执行的线程等待从队列中take()一些东西。

关于java - 阻塞方法引起的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33452852/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com