美文网首页
Android单例模式中的双重判空

Android单例模式中的双重判空

作者: Gunter1993 | 来源:发表于2017-07-26 01:10 被阅读86次
    public class ApiManager  {
        private static volatile ApiManager mInstance; 
    
        private ApiManager() {
        }
    
        public static ApiManager getInstance() {
            if (mInstance == null) {   // 判空1
                synchronized (ApiManager.class) { 
                    if (mInstance == null) {   // 判空2
                        mInstance = new ApiManager();
                    }
                }
            }
            return mInstance;
        }
    
    }
    

    mInstance为什么要加volatile?

    假设线程A执行了mInstance = new ApiManager(),但没有及时刷新到主内存中,并且恰好在解锁后,线程B刚好进来执行锁区域内的if (mInstance == null) ,由于线程A没有把实例化后的mInstance刷新到主内存中,所以此时 mInstance == null为true,于是导致了多次实例化。而加了volatile可以让变量具备线程可见性,即保证:子线程读取到volatile变量时会立刻从主内存中取最新的值,子线程给volatile变量赋值后及时更新至主内存。(详情可参考《volatile及指令重排序》

    为什么要进行两次判空?

    1、假如没有判空1,只有判空2:
    降低了多线程下的执行效率。比方说:mInstance不为空,且线程A和线程B同时需要执行getInstance(),那么每次如果线程A持有锁,那么线程B就得进入阻塞状态,等线程A判空完毕后线程B才能继续执行,这不就降低了性能。有了判空1,那么当mInstance不为空时,线程A和线程B只需一步判空并且不会发生阻塞。

    2、假如没有判空2,只有判空1:
    多线程执行getInstance()有可能导致多次实例化。因为假设线程A执行了判空1后,线程B也开始执行判空1,此时线程A和线程B都满足了mInstance == null的条件,即使线程A实例化mInstance,也无法影响线程B实例化mInstance。

    相关文章

      网友评论

          本文标题:Android单例模式中的双重判空

          本文链接:https://www.haomeiwen.com/subject/mdpgkxtx.html