单例模式的懒汉式在多线程的问题

我们都知道,单例设计模式中有两种方法,一种是饿汉式,另外一种就是懒汉式,具体如下:

饿汉式:

package com.seven.exercise.testEception;

/**
 * 单例模式,饿汉式
 * @author Seven
 *
 */
public class SingleDemoHunger {

    private SingleDemoHunger() {

    }

    private static SingleDemoHunger sdh = new SingleDemoHunger();

    public static SingleDemoHunger getInstance() {
        return sdh;
    }

}

懒汉式:

package com.seven.exercise.testEception;

/**
 * 懒汉式
 * @author Seven
 *
 */
public class SingleDemo {

    /**
     * 私有化构造函数
     */
    private SingleDemo(){

    }

    private static SingleDemo singleDemo = null;

    /**
     * 提供获取实例的方法
     * @return
     */
    public static SingleDemo getInstance(){
        if(singleDemo==null){
            singleDemo = new SingleDemo();
        }
        return singleDemo;
    }
}

相信这两种方法大家都知道,但是没有有考虑过在多线程的情况下:
饿汉式属于立即加载,所以不存在在多线程中出现错误的情况;

但是懒汉式的话就有可能出现问题了,如多一个线程执行到判断是否为空的语句

if(singleDemo==null)

的时候,当前线程被阻塞,而第二个线程进来了,这样的话第二个线程创建了新的对象,那么第一个线程被唤醒的时候又创建多一个对象,这样在内存中就存在了两个对象,明显和单例设计模式不符,那么我们应该怎么做呢?

很简单,用 synchronized关键字就可以轻松解决:

package com.seven.exercise.testEception;

/**
 * 懒汉式
 * @author Seven
 *
 */
public class SingleDemo {

    /**
     * 私有化构造函数
     */
    private SingleDemo(){

    }

    private static SingleDemo singleDemo = null;

    /**
     * 提供获取实例的方法,用synchronized来解决多线程的问题.
     * @return
     */
    public static SingleDemo getInstance(){
        synchronized (SingleDemo.class) {
            if(singleDemo==null){
                singleDemo = new SingleDemo();
            }
        }
        return singleDemo;
    }

}

这样就不会出现多个实例的问题,但是如果这么做的话,同步锁肯定要消耗资源,这样的话就会降低效率,那么有什么办法可以提高效率呢?答案是有的,那就是通过二次判断,这样的话就不用每次都执行同步代码块,这样的话,只需第一次执行的时候比较占资源,以后的话就和之前的一样了:

package com.seven.exercise.testEception;

/**
 * 懒汉式
 * @author Seven
 *
 */
public class SingleDemo {

    /**
     * 私有化构造函数
     */
    private SingleDemo(){

    }

    private static SingleDemo singleDemo = null;

    /**
     * 提供获取实例的方法,用synchronized来解决多线程的问题.
     * @return
     */
    public static SingleDemo getInstance(){
        //二次判断提高效率
        if(singleDemo==null){
            synchronized (SingleDemo.class) {
                if(singleDemo==null){
                    singleDemo = new SingleDemo();
                }
            }
        }
        return singleDemo;
    }

}

所以,利用synchronized关键字解决多线程问题,用二次判断提高效率~

时间: 2024-10-14 16:33:56

单例模式的懒汉式在多线程的问题的相关文章

单例模式之懒汉式与饿汉式

懒汉式单例 package single;?public class Monitor { //开始没有班长,用静态属性表示 private static Monitor monitor=null; //构造方法私有化,防止出现多个班长对象 private Monitor(){}; public static Monitor getmonitor(){ if(monitor==null){ monitor=new Monitor(); } return monitor; }} 首先班里没有班长,用

单例模式之懒汉式

?? //单例模式之懒汉式 class Singleton{ private static Singleton instance = null; private Singleton(){ } public static Singleton getSingleton(){ if(instance == null){ //同步代码块,保证安全性 synchronized(Singleton.class){ if(instance == null){ instance = new Singleton(

单例模式(饿汉式单例模式与懒汉式单例模式)

首先弄清楚什么是单例模式? 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案 单例模式的特点:(单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例) 1.该类只能有一个实例 2.该类只能自己创建这个唯一实例,且别人对该类无法创建实例 3.该类提供一个公开的方法public

单例模式(懒汉式单例、饿汉式单例、登记式单例)

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建.这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象. 注意: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 介绍 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点.

饿汉式单例模式和懒汉式单例模式

饿汉式单例模式 /** * 饿汉式单例模式 */ package com.you.hai.model; /** * @author YouHaiDong * */ public class Singleton { //实例化 private static Singleton instance = new Singleton(); /** * 无参构造函数私有化 */ private Singleton() { } /** * 通过该方法获取实例对象 * @return */ public sta

单例模式中懒汉式和恶汉式

1.单例模式:一.懒汉式://懒汉式单例类.延迟加载,在第一次调用的时候实例化自己public class SingleTon{ private static SingleTon instance: private SingleTon(){} public static synchronized SingleTon getInstance(){//这种方式在方法上加同步,每次调用该方法都要同步 if(instance==null){ instance = new SingleTon(); } r

单例设计模式---懒汉式的多线程安全隐患

public class Single {    private static Single s=null;    private Single(){            }        public static Single getInstance(){/*        if(s==null){  //如果是多线程,会出现多个类名进来,可能冻结,然后醒来加载多个对象            s=new Single(); //然后new 出多个对象        }        ret

设计模式课程 设计模式精讲 8-2 单例设计模式-懒汉式及多线程Debug实战

1 主要内容 1.1 核心功能点 2 代码演练 2.1 单线程调用 2.2 多线程调用 1 主要内容 1.1 核心功能点 2 代码演练 2.1 单线程调用 测试类: package com.geely.design.pattern.creational.singleton; public class Test { public static void main(String [] args){ //这样写异常,因为构造方法私有 // LazySingleton lazySingleton = n

PHP面向对象单例模式(懒汉式)

知识点: 一.三私一公: ①.私有静态属性,又来储存生成的唯一对象 ②.私有构造函数 ③.私有克隆函数,防止克隆--clone ④.公共静态方法,用来访问静态属性储存的对象,如果没有对象,则生成此单例 二.关键词instanceof 检查此变量是否为该类的对象.子类.或是实现接口.