public class Fern extends Thread
{
private String x = "varun";
public void run()
{
synchronized(Fern.class){
System.out.println(x);
try {
sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
x = "Anku";
}
}
public static void main(String args[]) throws Exception
{
Fern f = new Fern();
Thread t1 = new Thread(new Fern());
Thread t2 = new Thread(new Fern());
t1.start();
t2.start();
}
}
输出是: VARUN VARUN
由于块已经在Fern.class上同步,因此只允许一个线程一次进入块,而不管它属于哪个实例,因为对于所有实例,该类只有一个锁。如果我用一个Fern对象替换Thread构造函数中的新Fern(),则输出为: VARUN Anku。 这种行为就是我曾经同步过的(这个)。 我不明白为什么会发生这种情况,因为我已经同步了
答案 0 :(得分:3)
x
不是static
变量。将其更改为static
。
static String x =“varun”;
修改强>:
或将相同的对象作为参数传递给t1
和t2
。
Fern f = new Fern();
Thread t1 = new Thread(f); // pass the same object
Thread t2 = new Thread(f);
答案 1 :(得分:2)
x
是一个实例变量 - 换句话说,即使一次只有一个线程可以进入该块,它们也会查看不同的变量。更改第一个线程中x
的值不会影响第二个线程正在查看的x
。
换句话说,同步是“正确的”(如果您不希望多个线程进入该块,无论实例如何),但您的数据访问没有按照您的想法进行应该。
作为旁注,我个人更喜欢锁定我的班级只能 的参考文献。
作为另一个旁注,如果Fern
实施Runnable
而不是扩展Thread
会更好 - 您当前正在将一个线程传递给另一个线程构造函数,没有多大意义......
答案 2 :(得分:2)
线程的每个实例中的x
是不同的。在这两种情况下,请private static String x
使用共享的x
。
答案 3 :(得分:1)
这与同步无关。 x
是一个实例变量,因此每个Fern
实例都有自己的副本,初始化为“varun”,然后打印,然后设置为“Anku”。
答案 4 :(得分:0)
因为您有两个不同的Fern
个实例,所以其中一个实例更改了其x
字段的值这一事实并未见到另一个实例。 (我猜,因为你没有给出x
的声明。要获得更好的答案,只发布完整的代码。)