线程安全的单例模式

攻城狮 攻城狮     2022-08-14     146

关键词:

1. 全局变量的缺点:

必须在程序一开始就创建好对象,如果程序在这次的执行过程中又一直没用到它,就非常耗费资源。

 

2. 经典的单例模式实现:

Java代码
public class Singleton {    
      //用一个静态变量来记录Singleton类的唯一实例   
      private static Singleton uniqueInstance;
      private Singleton() {}   
           
      //注意这个方法也是静态的   
      public static Singleton getInstance() {    
           if(uniqueInstance == null) {   
             uniqueInstance = new Singleton();   
           }   
           return uniqueInstance;   
      }   
}  

    单例常被用来管理共享的资源,例如数据库连接、线程池、缓存、注册表。

    单例模式确保一个类只有一个实例,并提供一个全局访问点。

    这个模式的问题:在多线程时,并不能保证这个类只被实例化一次。

 

3. 处理多线程:

Java代码
public class Singleton {    
    //用一个静态变量来记录Singleton类的唯一实例   
    private static Singleton uniqueInstance;   
    
    private Singleton() {}   
           
    //注意这个方法也是静态的   
    public static synchronized Singleton getInstance() {    
        if(uniqueInstance == null) {   
             uniqueInstance = new Singleton();   
         }   
         return uniqueInstance;   
    }   
}  

 

   通过增加synchronized关键字到getInstance()方法中,迫使每个线程在进入方法之前,要先等别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法。

 

   这种方法存在的问题:只有第一次执行此方法时,才真正需要同步。换句话说,一旦设置好uniqueInstance变量,就不再需要同步这个方法了。之后每次调用这个方法,同步都是一种浪费。

 

4.改善多线程

 

4.1 如果getInstance()的性能对应用程序不是很关键,就不用优化了

4.2 使用急切创建实例,而不用延迟实例化的做法

Java代码
public class Singleton {
    private static Singleton uniqueInstance = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {    
         return uniqueInstance;   
    }
}

   标红的语句在静态初始化器(static initializer)中创建单例,这保证了线程安全。

   利用这个做法,JVM在加载这个类时马上创建此唯一的单件实例。JVM保证任何线程访问uniqueInstance静态变量之前,一定先创建些实例。

 

   4.3 用“双重检查加锁”,在getInstance()中减少使用同步

    首先检查实例是否已经创建,如果尚未创建,才进行同步。这样一来,只有第一次会同步,这正是我们想要的。

Java代码

 

public class Singleton {
    private volatile static Singleton uniqueInstance;
    private Singleton() {}
    public static Singleton getInstance() {    
    if(uniqueInstance == null) {//(1)
//只有第一次才彻底执行这里的代码   
       synchronized() {   
          //再检查一次   
          if(uniqueInstance == null)   
        uniqueInstance = new Singleton();   
       }   
    }   
         return uniqueInstance;   
    }   
}  

   在最开始如果有1、2、3个线程走到了(1)处,假设1进入了同步块,2、3等待。1实例化后,2进入同步块,发现uniqueInstance已经不为空,跳出同步块。接着3进入,又跳出同步块。

    volatile关键字确保:当uniqueInstance变量被初始化成Singleton实例时,多个线程正确地uniqueInstance变量。如果性能是你关心的重点,那么这个做法可以帮你大大地减少getInstance()的时间耗费。

高并发下线程安全的单例模式

...现方式,你是否都了解呢?高并发下如何保证单例模式的线程安全性呢?如何保证序列化后的单例对象在反序列化后任然是单例的呢?这些问题在看了本文之后都会一一的告诉你答案,赶快来阅读吧!什么是单例模式?在文 查看详情

线程安全的单例模式(代码片段)

饿汉模式1publicclassSingle23privatestaticSingleinstance=newSingle();45privateSingle()6System.out.println("Single:"+System.nanoTime());789publicstaticSinglegetInstance()10returninstance;1112  查看详情

c++的单例模式与线程安全单例模式(懒汉/饿汉)

1教科书里的单例模式  我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个privatestatic的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法... 查看详情

多线程阻塞队列定时器线程安全的单例模式的原理及实现(代码片段)

文章目录1.线程安全版本的单例模式1.1单例模式介绍1.2实现线程安全版本的懒汉模式2.阻塞队列2.1阻塞队列介绍2.2标准库中的阻塞队列2.3实现阻塞队列2.4生产者消费者模型3.定时器3.1定时器介绍3.2标准库中的定时器3.3实现定时器1.... 查看详情

多线程阻塞队列定时器线程安全的单例模式的原理及实现(代码片段)

文章目录1.线程安全版本的单例模式1.1单例模式介绍1.2实现线程安全版本的懒汉模式2.阻塞队列2.1阻塞队列介绍2.2标准库中的阻塞队列2.3实现阻塞队列2.4生产者消费者模型3.定时器3.1定时器介绍3.2标准库中的定时器3.3实现定时器1.... 查看详情

java基础——线程安全的单例模式懒汉式

packagesavesingleton;/*使用同步将单例模式中的懒汉式改写成线程安全的@authorzsben@create2020-01-0322:22*/classBank{privateBank(){}privatestaticBankinstance=null;/*publicstaticsynchronizedBankgetInstance(){if(instance==null){ 查看详情

线程安全的单例模式(代码片段)

一饿汉模式packagecom.thread;publicclassTest8publicstaticvoidmain(String[]args)MyThreadt1=newMyThread();MyThreadt2=newMyThread();MyThreadt3=newMyThread();t1.start();t2.start();t3.start();classMyObjectp 查看详情

java实现线程安全的单例模式

一、平时使用的软件中,例如回收站、线程池、文件系统等,都只有一个实例,这些都是单例模式的典型应用。  单例模式:确保某个类只有一个实例,并提供一个全局访问点来访问这个实例。  单例模式有三个要点:  ... 查看详情

多线程实现单例模式(饿汉懒汉)实现线程安全的单例模式(双重效验锁)(代码片段)

...比饿汉模式好。主要因为懒汉模式的效率更高1.饿汉模式(线程安全)//饿汉模 查看详情

线程安全的单例模式的几种实现

单例模式是一种常见的设计模式;JavaSingleton模式就为我们提供了这样实现的可能。使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收(garbagecollection)。 单例模式也是一种比较常见的设... 查看详情

dcl双检查锁机制实现的线程安全的单例模式

publicclassMyObject{privatevolatilestaticMyObjectmyObject;privateMyObject(){}publicstaticMyObjectgetInstance(){try{if(myObject!=null){}else{Thread.sleep(3000);synchronized(MyObject.class){if(myObject= 查看详情

推荐使用的三种无线程安全问题的单例模式(代码片段)

1、饿汉式publicclassSingletonprivatestaticSingletoninstance=newSingleton();privateSingleton()publicstaticSingletongetInstance()returninstance;2、懒汉式的双重检查锁定publicclassSingleton2privateSingleton2()p 查看详情

线程安全的单实例模式

我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个privatestatic的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类唯一的实例。... 查看详情

多线程下的单例模式

...现方式,你是否都了解呢?高并发下如何保证单例模式的线程安全性呢?如何保证序列化后的单例对象在反序列化后任然是单例的呢?这些问题在看了本文之后都会一一的告诉你答案,赶快来阅读吧!什么是单例模式?在文章开... 查看详情

怎么实现一个线程安全的单例模式

设计模式在面试中挺常考的,单例模式是考的最多的。线程安全的单例还有很多种实现方法。可以使用静态内部类、双重校验锁、静态代码块等。1、饿汉式public class Singleton()    private static Singleton&nb... 查看详情

线程安全的单例模式(代码片段)

... 双重检查锁与延迟初始化(懒汉式)    在Java多线程程序中,有时候需要采用延迟初始化来降低初始化类和创建对象的开销,在使用这些对象时才进行初始化。延迟初始化需要注意线程安全  问题,否则就容易出现问... 查看详情

线程安全的 C# 单例模式

】线程安全的C#单例模式【英文标题】:ThreadSafeC#SingletonPattern【发布时间】:2012-09-0105:41:18【问题描述】:我对这里记录的单例模式有一些疑问:http://msdn.microsoft.com/en-us/library/ff650316.aspx以下代码摘自文章:usingSystem;publicsealedclas... 查看详情

单例模式

1.由单例模式中关于static的问题2.为什么要有单例模式3.多线程安全的单例模式4.模版类的单例模式的实现 1. 由单例模式中关于static的问题:“静态成员函数调用了非静态成员函数(构造函数)”最简单的单例模式如下:1class... 查看详情