我有以下代码:
public class Experimenter implements Runnable
{
private volatile Integer a = new Integer(0);
public Experimenter() throws Exception
{
System.out.println("start");
}
public void funk() throws InterruptedException
{
synchronized (a)
{
System.out.println("in");
Thread.sleep(5000);
System.out.println("out");
}
}
public static void main(String[] args) throws Exception
{
Thread a = new Thread(new Experimenter(), "a");
Thread b = new Thread(new Experimenter(), "b");
Thread c = new Thread(new Experimenter(), "c");
Thread d = new Thread(new Experimenter(), "d");
Thread e = new Thread(new Experimenter(), "e");
a.start();
b.start();
c.start();
d.start();
e.start();
}
@Override
public void run()
{
try
{
funk();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
我原以为一次只有一个线程可以使用 synchronized block ,它会打印如下内容,每次输入和输出之间有 5 秒的间隔:
start
start
start
start
start
in
out
in
out
in
out
in
out
in
out
但是,我得到了以下信息。所有的输入,5 秒后,所有的输出。:
start
start
start
start
start
in
in
in
in
in
out
out
out
out
out
谁能帮忙解释一下?
最佳答案
非常简单:您的a
不会在您的任何Experimenter
之间共享;它是一个实例变量,每个 Experimenter
一个。顺便说一句,volatile
在这种情况下几乎没用。
如果你想要一个共享锁,让它成为一个private static final
变量。在这种情况下也不需要 volatile
!
但我会选择@JBNizet 的解决方案,它更简洁。
编辑:为什么是final
?因为它保证一旦初始化就永远不会改变;但是 final
变量最重要的方面来自 Java 内存模型,它指出 final
变量的初始化先于任何读取这个变量。这是一个非常强大的规则。
关于Java 同步块(synchronized block)意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27705992/