线程安全且按需构建的单例模式

单例模式,即保证某个类只有一个实例,网上有很多构造单例的方法,或多或少有其缺陷。如DCL(double check lock)模式,不能保证对象能被正确发布。

使用静态变量

public class CarFactory {
  private static CarFactory instance = new CarFactory();
  private CarFactory(){
  }
  public static CarFactory getInstance(){
    return instance;
  }
}

这个能保证安全性,但是在不需要引用对象的instance时,对象也可能被创建,会造成资源浪费

Double Check Lock(DCL)

public class CarFactory {
  private static CarFactory instance = null;
  private CarFactory(){
  }
  public static CarFactory getInstance(){
    if(instance == null){
      synchronized (CarFactory.class){
        if(instance == null){
          instance = new CarFactory();
        }
      }
    }
    return instance;
  }
}

这个是网上流传的非常广泛的单例模式构造方法,据说既能保证安全性,又能按需创建。但是仔细想想,在线程A和线程B同时调用getInstance()方法时,线程A调用了instance = new CarFactory(),但是对象还没有初始化完毕,这时instance已经不为null,而线程B会认为instance不为null,直接使用instance。这就会造成引用逸出,根据JMM,线程A中初始的数据对线程B的可见性没法保证。这可能会产生很严重的后果

线程安全&&按需创建

public class CarFactory {
  private CarFactory(){
  }
  public static class SingleInstance{
    static CarFactory instance = new CarFactory();
  }
  public static CarFactory getInstance(){
    return SingleInstance.instance;
  }
}

只有在调用getInstance()方法时,才能创建CarFactory实例,而且保证了线程安全性。

时间: 2024-10-28 11:11:50

线程安全且按需构建的单例模式的相关文章

一个简单线程池的实现---需进一步完善

1.定义一个任务结构体,和一个线程池结构体 struct task{ void *(*p)(void*);//需要实现的函数: void *arg;//函数所带的参数 struct task *next;};struct pthread_pool{ pthread_mutex_t mutex;//线程锁 pthread_cond_t cond;//条件变量 pthread_t *tids;//线程id int thread_nums;//需创建的线程的数量 struct task *head;任

线程安全的多参构建器实现

适用情况: 1:参数多 2:需要带参构造器多(避免冗余) 3:多线程并发情况 /** * 线程安全的多参构建器实现 *  * @author 祥少 * */public class Test {    private int a;    private int b;    private int c; @Override    public String toString() {        return "Test [a=" + a + ", b=" + b +

C#在工作线程刷新主界面控件状态小结,单例模式、委托

今日项目开发中需要在服务器界面实时显示客户端连接状态,使用C#的反射机制解决了问题.由于项目比较复杂,现结合一个小例子,对使用C#委托反射机制刷新主界面上的控件状态进行简单小结,希望对新手有所帮助. 一.新建一个C# winform工程:Form_MainUI,界面布局如图1. 代码如下: 1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data;

三种方式构建C#单例模式

1 /// <summary> 2 /// 双检锁实现单例 3 /// </summary> 4 public sealed class SingletonDoubleCheck 5 { 6 //s_lock对象是实现线程安全所需要的,定义这个对象时,我们假设创建单例对象的代价高于创建一个System.Object对象 7 //并假设可能根本不需要创建单例对象,否则,更经济.更简单的做法是在一个类构造器中创建单例对象 8 private static Object s_lock =

如何保证单例模式在多线程中的线程安全性

对大数据.分布式.高并发等知识的学习必须要有多线程的基础.这里讨论一下如何在多线程的情况下设计单例模式.在23中设计模式中单例模式是比较常见的,在非多线程的情况下写单例模式,考虑的东西会很少,但是如果将多线程和单例模式结合起来,考虑的事情就变多了,如果使用不当(特别是在生成环境中)就会造成严重的后果.所以如何使单例模式在多线程中是安全的显得尤为重要,下面介绍各个方式的优缺点以及可用性: 1.立即加载(饿汉模式) 立即加载模式就是在调用getInstance()方法前,实例就被创建了,例: pub

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

单例模式是一种常见的设计模式:Java Singleton 模式就为我们提供了这样实现的可能.使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数, 有利于Java垃圾回收(garbage collection). 单例模式也是一种比较常见的设计模式,它到底能带给我们什么好处呢?其实无非是三个方面的作用: 1.控制资源的使用,通过线程同步来控制资源的并发访问: 2.控制实例产生的数量,达到节约资源的目的. 3.作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让

设计模式:单例模式的写法(基础写法和线程安全写法)

单例模式的写法非常多.先给出一种最基础的写法: (A种写法): package singleton; public class SingletonInstance { private static SingletonInstance mSingletonInstance = null; // 特意将构造函数设置成 private,防止外部使用者new SingletonInstance(). private SingletonInstance() { } public static Single

java并发 之构建线程安全程序 (2)

我们知道线程安全的根本原因在于: 多个线程访问一个共享资源,并且对该共享资源进行非原子性修改. 在一个大型的程序中要找出哪些线程访问了同一个资源是非常复杂且容易出错的.所以在开发线程安全程序时要将共享资源进行封装,控制线程对其的访问. 在java中,面向对象提供了封装和访问内部资源的方式,通过面相对象,不仅可以编写出结构优雅.可维护性高的类,而且有助于编写出线程安全的类. 在java中通过面向对象技术封装和控制共享资源访问. 使用面向对象不仅使得便于封装和控制共享资源,而且也易于构建多个共享资源

线程(代码实现)详解

在计算机科学中,一个线程执行的是,可以独立地被一个管理编程指令的最小序列调度,这是通常的的一部分的操作系统.线程和所述的实施过程的操作系统之间的不同,但在大多数情况下,一个线程的过程的一个组成部分.多个线程可以在一个过程中存在,执行同时和共享的资源,例如存储器,而不同的过程不共享这些资源.特别是,一个进程的线程共享其可执行代码和它的变量在任何给定时间的值. 具有单处理器系统通常实现由多线程时间分片:所述中央处理单元(CPU)的不同之间切换的软件线程.这种上下文切换通常发生非常频繁,并迅速不够,用