多线程中static方法访问static变量会造成同步问题. 困惑

时间:2021-09-05 18:07:13
public class MyClass {
private static MyClass _instance;
public static MyClass getInstance() {
 if(_instance != null) {
  _instance = new MyClass();
  }
return _instance;
  }
}
如果有两个线程同时调用MyClass.getInstance()方法,就有可能造成MyClass的构造方法被调用两次。
为什么?
而如果这么写就不会public class MyClass { 
 private static MyClass _instance = new MyClass(); 
 public static MyClass getInstance() {  
  return _instance; 
 }
}

12 个解决方案

#1


如果有两个线程同时调用MyClass.getInstance()方法,就有可能造成MyClass的构造方法被调用两次。 
为什么?
 
因为你没有把他的构造函数私有化。
改成

public class MyClass { 
private static MyClass _instance; 
private MyClass(){

}


public static MyClass getInstance() { 
 if(_instance != null) { 
  _instance = new MyClass(); 
  } 
return _instance; 
  } 


就不会出现你说的情况了。

#2


我的意思为什么会构造方法被调用两次,而不是如何不让他构造两次的问题。下面我不是也说了一种方法,也可以不让他构造两次。

#3


你的getInstance()方法如果加上同步就不会出现你说的2吃调用构造方法的情况了.
至于为甚么,其实很简单.
在多线程的情况下, 同时有2个线程调用getInstance方法,在判断 if(_instance != null)的时候2个都成立了.
但是之后其中一个执行了构造方法的调用,另外一个接着也执行了构造方法的调用.于是就产生了你说的这种情况了

#4


不对啊.这里的判断应该是 if(_instance == null)而不是!=吧.

#5


引用 4 楼 kekeemx 的回复:
不对啊.这里的判断应该是 if(_instance == null)而不是!=吧.

同4l

#6


额。是== ,但是instance的值是static的啊。我感觉还是最终得到一个实例呢?在一个如果一个变量是static的话,两个线程可以同时访问该变量吗?

#7


因为getInstance方法不是同步的,所以有可能多个线程同时进入该方法
例如,线程1刚执行完 if(_instance != null) { 还没有执行_instance = new MyClass();
这时线程2也开始 if(_instance != null),这种情况就会造成实例化两个MyClass对象


#8


如果一个变量是static的话,两个线程可以同时访问该变量吗?也就是说static变量是线程同步的吗?

#9


引用 8 楼 sdzbfq 的回复:
如果一个变量是static的话,两个线程可以同时访问该变量吗?也就是说static变量是线程同步的吗?

这句话本身就有毛病,既然可以多个线程同时访问,那就不是线程同步的
还有,是不是static跟是不是线程同步的没有什么必然的联系

#10


引用 9 楼 yeecheng 的回复:
引用 8 楼 sdzbfq 的回复:
如果一个变量是static的话,两个线程可以同时访问该变量吗?也就是说static变量是线程同步的吗? 
 
这句话本身就有毛病,既然可以多个线程同时访问,那就不是线程同步的 
还有,是不是static跟是不是线程同步的没有什么必然的联系

我是问两个线程可以同时吗????不是说可以~!

#11


结贴。搞明白了我,谢谢给位!

#12


引用 1 楼 caoyinghui1986 的回复:
如果有两个线程同时调用MyClass.getInstance()方法,就有可能造成MyClass的构造方法被调用两次。  
为什么?  
因为你没有把他的构造函数私有化。 
改成 

public class MyClass {  
private static MyClass _instance;  
private MyClass(){ 



public static MyClass getInstance() {  
 if(_instance != null) {  
  _instance = new MyClass();  
  }  
return _instance;  
  }  
}  

就不会出现你说…

类的构造方法不能是私有的,因此你的做法是不对的。

#1


如果有两个线程同时调用MyClass.getInstance()方法,就有可能造成MyClass的构造方法被调用两次。 
为什么?
 
因为你没有把他的构造函数私有化。
改成

public class MyClass { 
private static MyClass _instance; 
private MyClass(){

}


public static MyClass getInstance() { 
 if(_instance != null) { 
  _instance = new MyClass(); 
  } 
return _instance; 
  } 


就不会出现你说的情况了。

#2


我的意思为什么会构造方法被调用两次,而不是如何不让他构造两次的问题。下面我不是也说了一种方法,也可以不让他构造两次。

#3


你的getInstance()方法如果加上同步就不会出现你说的2吃调用构造方法的情况了.
至于为甚么,其实很简单.
在多线程的情况下, 同时有2个线程调用getInstance方法,在判断 if(_instance != null)的时候2个都成立了.
但是之后其中一个执行了构造方法的调用,另外一个接着也执行了构造方法的调用.于是就产生了你说的这种情况了

#4


不对啊.这里的判断应该是 if(_instance == null)而不是!=吧.

#5


引用 4 楼 kekeemx 的回复:
不对啊.这里的判断应该是 if(_instance == null)而不是!=吧.

同4l

#6


额。是== ,但是instance的值是static的啊。我感觉还是最终得到一个实例呢?在一个如果一个变量是static的话,两个线程可以同时访问该变量吗?

#7


因为getInstance方法不是同步的,所以有可能多个线程同时进入该方法
例如,线程1刚执行完 if(_instance != null) { 还没有执行_instance = new MyClass();
这时线程2也开始 if(_instance != null),这种情况就会造成实例化两个MyClass对象


#8


如果一个变量是static的话,两个线程可以同时访问该变量吗?也就是说static变量是线程同步的吗?

#9


引用 8 楼 sdzbfq 的回复:
如果一个变量是static的话,两个线程可以同时访问该变量吗?也就是说static变量是线程同步的吗?

这句话本身就有毛病,既然可以多个线程同时访问,那就不是线程同步的
还有,是不是static跟是不是线程同步的没有什么必然的联系

#10


引用 9 楼 yeecheng 的回复:
引用 8 楼 sdzbfq 的回复:
如果一个变量是static的话,两个线程可以同时访问该变量吗?也就是说static变量是线程同步的吗? 
 
这句话本身就有毛病,既然可以多个线程同时访问,那就不是线程同步的 
还有,是不是static跟是不是线程同步的没有什么必然的联系

我是问两个线程可以同时吗????不是说可以~!

#11


结贴。搞明白了我,谢谢给位!

#12


引用 1 楼 caoyinghui1986 的回复:
如果有两个线程同时调用MyClass.getInstance()方法,就有可能造成MyClass的构造方法被调用两次。  
为什么?  
因为你没有把他的构造函数私有化。 
改成 

public class MyClass {  
private static MyClass _instance;  
private MyClass(){ 



public static MyClass getInstance() {  
 if(_instance != null) {  
  _instance = new MyClass();  
  }  
return _instance;  
  }  
}  

就不会出现你说…

类的构造方法不能是私有的,因此你的做法是不对的。