zoukankan      html  css  js  c++  java
  • 线程安全的单例模式

    方案一:Double Check Lock
    public class ThreadSafeSingleton {
        private static ThreadSafeSingleton sThreadSafeSingleton;
    
        public static ThreadSafeSingleton getInstance() {
            if (sThreadSafeSingleton == null) {
                createSingleton();
            }
            return sThreadSafeSingleton;
        }
    
        private synchronized static void createSingleton() {
            if (sThreadSafeSingleton == null) {
                sThreadSafeSingleton = new ThreadSafeSingleton();
            }
        }
    
    方案二:内部类延迟加载实例化
    public class ThreadSafeSingleton {
    public static ThreadSafeSingleton getInstance() {
    return ThreadSafeSingletonHolder.sThreadSafeSingleton;
    }

    private static class ThreadSafeSingletonHolder {
    private static ThreadSafeSingleton sThreadSafeSingleton = new ThreadSafeSingleton();
    }
    }

    方案三:类初始化时创建静态成员
    public class ThreadSafeSingleton {
      private static ThreadSafeSingleton sThreadSafeSingleton = new ThreadSafeSingleton();
    public static ThreadSafeSingleton getInstance() {
        return sThreadSafeSingleton;
       }
    }

    测试代码: public static void main(String[] args) { for (int i = 0; i<3; ++i) { new Thread(new Runnable() { @Override public void run() { TestUtils.print(String.format("thread=%s, singleton=%s", Thread.currentThread().getName(), getInstance())); } }).start(); } }
    两个的输出结果是一样的,根据Java Concurrency in practice的理论,方案一存在unsafe publication风险,
    即Thread A在初始化sThreadSafeSingleton时,Thread B在读取该变量,由于此处读取操作无锁,
    若compile reorder后,sThreadSafeSingleton的赋值操作在构造函数之前,可能会导致Thread B读取了一个不完整的sThreadSafeSingleton对象。
    而方案二利用内部类延迟加载(调用getInstance时才初始化内部类,然后实例化对象),因此无需锁操作,性能和安全性上较方案一优。

    输出结果为:

    thread=Thread-1, singleton=com.tony.ThreadSafeSingleton@142b7711
    thread=Thread-2, singleton=com.tony.ThreadSafeSingleton@142b7711
    thread=Thread-0, singleton=com.tony.ThreadSafeSingleton@142b7711

    方案二、三的差别在实例化的时机上,方案三在初始化类时便会实例化(如调用ThreadSafeSingleton静态成员、函数时触发),

    方案二在初始化内部类时才会触发实例化(主动式引用方式,即调用getInstance,而引用其他静态变量或静态函数时不会触发内部类初始化,

    从而实现lazy initialization + thread safe instance的效果)。

  • 相关阅读:
    [bug] MySQL: The user specified as a definer ('root'@'%') does not exist
    [java] Maven安装本地jar包
    [bug] Openresty:content_by_lua_file 404
    [bug] Failed building wheel for xxx
    [bug] TypeError : unsupported operand type(s) for += : 'NoneType' and 'int'
    [Python] Flask从0到1开发轻量级网页
    [bug]Flask:KeyError: 'A secret key is required to use CSRF.'
    [bug] sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1054, "Unknown column 'recevie_name' in 'field list'")
    mac os 解决Error: EMFILE: too many open files错误
    从零开始的react入门教程(一),让我们从hello world开始
  • 原文地址:https://www.cnblogs.com/tonybright/p/4774953.html
Copyright © 2011-2022 走看看