静态内部类实现单例模式以及不需要显式使用锁的原因

先说结论:

静态内部类实现单例模式,是借助了类加载器加载类的特性实现的,类加载器在加载类时使用了synchronized关键字.

单例模式代码:

public class SingletonDemo {

    public static void main(String[] args) {
        SingletonDemo sd1 = getInstance();
        SingletonDemo sd2 = getInstance();
        System.out.println(sd1.equals(sd2));       
    }

    private SingletonDemo(){};

    private static class SingletonHolder{
        private static SingletonDemo INSTANCE = new SingletonDemo();

    }
    
    public static SingletonDemo getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

输出为:

true

首次执行getInstance()方法,调用SingletonHolder中的静态属性INSTANCE时,触发SingletonHolder类的加载,而new SingletonDemo()也会被执行,且只被执行一次.

在多线程环境下是如何实现同步的呢?这就要看ClassLoader类的源码了:


    public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

经过调试,可以确定的是,程序先进入了上面这个方法.但是点击F7进入的却不是下面这个方法:

 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

进入的是ClassLoaders.AppClassLoader类中的loadClass()方法:

        @Override
        protected Class<?> loadClass(String cn, boolean resolve)
            throws ClassNotFoundException
        {
            // for compatibility reasons, say where restricted package list has
            // been updated to list API packages in the unnamed module.
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                int i = cn.lastIndexOf('.');
                if (i != -1) {
                    sm.checkPackageAccess(cn.substring(0, i));
                }
            }

            return super.loadClass(cn, resolve);
        }

执行super.loadClass(),进入了BuiltinClassLoader类中的loadClass()方法:

    @Override
    protected Class<?> loadClass(String cn, boolean resolve)
        throws ClassNotFoundException
    {
        Class<?> c = loadClassOrNull(cn, resolve);
        if (c == null)
            throw new ClassNotFoundException(cn);
        return c;
    }

执行loadClassOrNull()方法,然后进入同一个类中的loadClassOrNull()方法:

 protected Class<?> loadClassOrNull(String cn, boolean resolve) {
        synchronized (getClassLoadingLock(cn)) {
            // check if already loaded
            Class<?> c = findLoadedClass(cn);

            if (c == null) {

                // find the candidate module for this class
                LoadedModule loadedModule = findLoadedModule(cn);
                if (loadedModule != null) {

                    // package is in a module
                    BuiltinClassLoader loader = loadedModule.loader();
                    if (loader == this) {
                        if (VM.isModuleSystemInited()) {
                            c = findClassInModuleOrNull(loadedModule, cn);
                        }
                    } else {
                        // delegate to the other loader
                        c = loader.loadClassOrNull(cn);
                    }

                } else {

                    // check parent
                    if (parent != null) {
                        c = parent.loadClassOrNull(cn);
                    }

                    // check class path
                    if (c == null && hasClassPath() && VM.isModuleSystemInited()) {
                        c = findClassOnClassPathOrNull(cn);
                    }
                }

            }

            if (resolve && c != null)
                resolveClass(c);

            return c;
        }
    }

终于出现了,synchronized关键字!

调用链很长,但是都是在synchronized中了,就不继续往下走了.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章