【发布时间】:2020-07-17 05:49:00
【问题描述】:
我有这个带有单例模式的示例代码:
class Singleton{
private static Singleton instance;
private int count;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
public int getCount(){return count;}
public void setCount(int count){this.count=count;}
public static void main(String[] args) throws InterruptedException{
Thread t1=new Thread(()->{
while(Singleton.getInstance().getCount()==0){
//loop
}
System.out.println("exist t1 with count="+Singleton.getInstance().getCount());
});
t1.start();
Thread.sleep(1000); //time out to force t1 start before t2
Thread t2=new Thread(()->{
Singleton.getInstance().setCount(10000);
});
t2.start();
t1.join();
t2.join();
}
}
我有一个问题:方法getCount 和setCount 在两个线程t1 中调用,t2 是线程安全的,不是吗?
【问题讨论】:
-
"方法
getCount和setCount在两个线程 t1 中调用,t2 是线程安全的,不是吗?" - 不,它们不是线程安全的,并且 singleton 在这方面是完全不相关的。假设两个线程都完成了对返回相同实例的Singleton.getInstance()的调用,并且只有在这之后两个线程才同时调用getCount和setCount。这些方法访问相同的 non-volatile 变量<instance>.count而不进行同步,其中一种访问 - 来自setCount- 是 write 访问。根据定义,这是一场数据竞赛。 -
我认为这是一个正确的答案。如果对对象实例的引用对其他线程可见(例如使用 volatile),则该对象的成员不能是线程安全的。
标签: java multithreading synchronized happens-before