单例模式之懒汉的并发问题

饿汉模式:

class Single{

  private staitc final Single s= new Single();

  private Single(){}

  public static Single getSingle(){

    return s;

  }

}  

懒汉模式:

class Single{

  private static Single s= null;

  private Single(){}

  public static Single getSingle(){

    if(s == null){

        -->A线程

        -->B线程

      s  =  new Single();

      return s;

    }  

  }

}  

在这里使用懒汉模式有一个安全性问题:

就是s为共享数据,可能会并发的访问getSingle()方法。当多线程访问时,一个A线程进来后,可能调用了sleep()方法在这里沉睡;一个B线程也可能在沉睡,当A线程醒来后,就会new一个对象,B线程醒来也会new一个对象;这样就不符合我们单例模式的特点了。

解决方案:在getSingle()方法前增加synchronized进行同步

另一个问题,当加了synchronized后,那么很多线程来访问时,都要判断一下锁是哪个,这就造成速率下降,解决方案如下:

public staitc Single getSingle(){

  if(s == null){

    synchronized(Single.class){  -->B线程,等着A解锁才让进去

      if(s == null){

          -->A线程

        s = new Single();

      }

    }

  return s;

  }

}

思路:

当s == null时,A线程进来了,他加了一下锁后进入第二个if(s ==null){},然后沉睡;此时,B也通过了第一个if(s == null),当B玩下执行时,遇到了synchronized(),发现这里A进行了加锁,没办法B线程只能等着,等A把锁解了。此时,A线程醒来了,它new 了一个对象后,继续玩下执行,然后把锁解了,这是s不等于null了。B发现A解锁了,它继续往下执行,发现s不等于null了,那它直接返回了A创建的那个对象s。当c线程访问getSingle方法时,只需判断s是否为null,而不用去判断锁对象了。因为s不等于null了,所以直接返回对象,这样就提高了效率

懒汉模式是延迟加载的实例,面对多线程访问时,需要进行同步代码块,为了增加效率,又要使用双重判断

注意:非静态的同步函数对象是this,静态的同步函数对象是:字节码对象。即类.class;

时间: 2024-10-15 22:24:43

单例模式之懒汉的并发问题的相关文章

单例模式(懒汉方式和饿汉方式)

Singleton 单例模式(懒汉方式和饿汉方式) 单例模式的概念: 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 关键点: 1)一个类只有一个实例       这是最基本的 2)它必须自行创建这个实例 3)它必须自行向整个系统提供这个实例 -----------------------------------------------------------------------------------------

javascript单例模式(懒汉 饿汉)

第一种:懒汉模式 var Singleton=(function(){ var instantiated; //比较懒,在类加载时,不创建实例,因此类加载速度快,但运行时获取对象的速度慢 function init(){ /*这里定义单例代码*/ return{ publicMethod:function(){ console.log('helloworld'); }, publicProperty:3 }; } return{ getInstance:function(){ if(!insta

单例模式之懒汉模式&恶汉模式

单例模式,其实就是对于一个类,只能新建一个对象,不能有多个重复的对象.这样使得在程序在运行时,比如日志加载时能找到唯一的对象,以至正确匹配.就类似于一山不能有二虎一样.主要的思想其实就是运用static,在类内部new一个自己的对象,再通过类方法返回这个对象.由于静态方法new出的对象,故其实有着同样的hashCode,也即同一个对象.一下是代码: Test.java package com.demo_type; public class Test { public static void ma

单例模式之懒汉模式,懒汉模式之高效模式,DLC双判断模式

import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 单例模式之懒汉模式 * 懒汉模式之高效模式 * DLC双判断模式 */ public class SingleClassLazySync { private static SingleClassLazySync sin

单例模式(懒汉)(一)

/** * 单例模式(懒汉) */ public class Single { private static Single single=null; private Single(){ } public static Single getInstance(){ if (single == null){ single=new Single(); } return single; } 测试是否为单例 public static void main(String[] args) { Single si

C#单例模式之懒汉 / 饿汉

在使用某个设计模式之前必须先了解使用它的优点: 1.单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例对象,减少了对象的创建,从而减轻了程序内存的开销. 2.单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案.3.说白了就是保证一个类仅有一个实例,并提供一个该实例的全

饿汉单例模式 and 懒汉单例模式

饿汉单例模式:主要就是利用static关键字,在类加载的时候生成实例,调用效率高 但是如果一直没有调用getInstance方法的话,就会造成资源浪费 具体实现如下: class Single{ private static Single single = new Single(); private Single() { } public static Single getInstance() { return single; } } 懒汉单例模式:主要就是在调用的的时候才产生实例,那么就要考虑

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

1 教科书里的单例模式 我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个private static的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类唯一的实例. 上代码: class singleton { protected: singleton(){} private: static singleton* p; public: static singleton* instance()

单例模式之 懒汉模式普通版

直接上代码: /* 单例模式可以保证:在一个程序当中,一个类有且只有一个实例,并提供一个访问 它的全局访问点 在程序设计当中,很多情况下需要确保一个类只有一个实例 例如: windopws系统中只能有一个窗口管理器 某个程序中只能有一个日志输出系统 一个GUI系统类库中,有且只有一个ImageManager */ #include <iostream> #include "C1.H" #include <windows.h> #include <proce