在我的计算机上,使用java 8,即使同步地图访问,以下程序也不会停止。 Aren那些同步的块会不会出现?
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run?
public class StopThread {
private static HashMap<String, String> stopRequested = new HashMap<String, String>();
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
synchronized (stopRequested) {
while (stopRequested.get("stop") == null)
i++;
}
System.out.println(i);
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
synchronized (stopRequested) {
stopRequested.put("stop", "true");
}
}
}
答案 0 :(得分:2)
这将永远运行。同步块中的while循环实际上是无限的,因为它是首先输入的 - 因此禁止输入第二个同步块。
答案 1 :(得分:1)
是的,这是预期的,你的backgroundThread在主线程之前持有锁,它不会释放它,直到主线程写入&#34;停止&#34;在地图上,主线程需要锁定才能将其写入&#34; stop&#34;所以基本上这是一个死锁。
有几种方法可以解决这个死锁,我的猜测是你要做的是看看在主线程写入之前你计算了多少次&#34;停止&#34;在地图中输入。 您可以在循环的每次迭代中简单地获取和释放锁,这对您的场景有意义。
while (stopRequested.get("stop") == null)
synchronized (stopRequested) {
i++;
}
另一个解决方案可能是使用concurrentHashMap,请查看此link以获取更多详细信息
答案 2 :(得分:1)
您在stopRequested
上有两个同步线程。在任何给定时间只允许运行一个synchronized
块。因为几乎总是这样,backgroundThread的synchronized
块首先运行,所以它永远不会退出,因此永远不会允许任何其他线程在stopRequested
上同步。
try {
int i = 0;
synchronized (stopRequested) {
while (stopRequested.get("stop") == null) {
stopRequested.wait();
i++;
}
}
System.out.println(i);
} catch (InterruptedException e) {
throw new RuntimeException(i);
}
// ...
synchronized (stopRequested) {
stopRequested.put("stop", "true");
stopRequested.notify();
}
这样做的原因是wait()
将暂时和原子地释放同步锁,允许另一个线程在该对象上同步。
请注意,必须在循环中调用wait(),该循环检查等待的条件,因为即使没有其他线程调用notify()
,wait()也可能偶尔返回。这种“虚假唤醒”是由于某些系统上线程的性质所致。
行为良好的线程会将整个等待循环放在try / catch块中,因此线程将在中断时退出。中断是来自其他某个线程的请求,要求您的线程停止正在执行的操作并彻底退出。
答案 3 :(得分:0)
感谢所有答案。实际上,这是一个僵局。工作同步是
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run?
public class StopThread {
private static HashMap<String, String> stopRequested = new HashMap<String, String>();
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (stopRequested())
i++;
System.out.println(i);
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
synchronized (stopRequested) {
stopRequested.put("stop", "true");
}
}
static boolean stopRequested()
{
synchronized (stopRequested) {
return stopRequested.get("stop") == null;
}
}
}