public class Singleton { private static Singleton instance; private static object _lock=new object(); private Singleton() { } public static Singleton GetInstance() { if(instance==null) { lock(_lock) { if(instance==null) { instance=new Singleton(); } } } return instance; } }
上面是所谓的懒汉单例模式,我疑惑的是:外层的if判断是原子操作吗?有没有可能线程1进行if判断的时候执行到一半,然后时间片用完,线程2得到执行权……这不就有问题吗?
很赞成 @Qlin的说法!因为加了锁,线程2是得不到执行权的,只能等待锁释放。。
假设外层的if判断不是原子操作,某一时刻,线程1和线程2都试图去执行外层if语句,竞争的结果是线程2得到CPU执行权,线程1在外层if语句处挂起(1挂起的时候instance还是空),2进入内层循环,2执行完毕,创建了一个实例,释放锁,然后1得到CPU执行权,由于1挂起的时候instance是空,所以对1来说外层if成立,进入内层循环,又创建了一个实例。这样就会导致有两个实例。
如果if(a==b)不是原子操作,我说这种情况应该是存在的。如有错误,请您指教。
@钱智慧: 1挂起的时候instance为空,进入内层的时候,instance不为空了。所以里面的那个if就起到作用了。所以就不会有两个实例了~
@幻天芒: 谢谢您 ,明白了。
@钱智慧: 外层if不是这种形式单例的必须,关键是锁里面的那个if,由于加锁很费时间,在外层进行一个空判断的话,可以减少加锁的次数。
cpu是单线程,只不过操作系统模拟出来的多线程,所以你说的问题不存在
就是因为怕这种问题 不是下面有一个lock么
假设外层的if判断不是原子操作,某一时刻,线程1和线程2都试图去执行外层if语句,竞争的结果是线程2得到CPU执行权,线程1在外层if语句处挂起(1挂起的时候instance还是空),2进入内层循环,2执行完毕,创建了一个实例,释放锁,然后1得到CPU执行权,由于1挂起的时候instance是空,所以对1来说外层if成立,进入内层循环,又创建了一个实例。这样就会导致有两个实例。
如果if(a==b)不是原子操作,我说这种情况应该是存在的。如有错误,请您指教。
不要外层的 if 也可以。
外层的if 作用:可以防止进入lock,lock 需要耗资源的,每次访问实例时 ,如果有对象了,就可不进lock,性能考虑。
里层的if才是单例的防止, 为了创建一个实例。
假设外层的if判断不是原子操作,某一时刻,线程1和线程2都试图去执行外层if语句,竞争的结果是线程2得到CPU执行权,线程1在外层if语句处挂起(1挂起的时候instance还是空),2进入内层循环,2执行完毕,创建了一个实例,释放锁,然后1得到CPU执行权,由于1挂起的时候instance是空,所以对1来说外层if成立,进入内层循环,又创建了一个实例。这样就会导致有两个实例。
如果if(a==b)不是原子操作,我说这种情况应该是存在的。如有错误,请您指教。