zoukankan      html  css  js  c++  java
  • 单例模式的懒汉式在多线程的问题

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

    饿汉式:

    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关键字解决多线程问题,用二次判断提高效率~

  • 相关阅读:
    JDBC-HikariCP
    11、JDBC-Druid
    JDBC-DBCP
    JDBC-C3P0
    第十七篇-使用RadioGroup实现单项选择
    第十六篇-使用CheckBox实现多项选择
    第一篇-ubuntu18.04访问共享文件夹
    第十五篇-EditText做简单的登录框
    第十四篇-ImageButton控制聚焦,单击,常态三种状态的显示背景
    第十三篇-通过Button设置文本背景颜色
  • 原文地址:https://www.cnblogs.com/sevenlin/p/sevenlin_thread20150809.html
Copyright © 2011-2022 走看看