线程安全的懒汉模式

时间:2024-4-4    作者:老大夫    分类: JAVA


之前讲的单例模式中的懒汉模式是在调用时才会生成一个对象以供使用,
为了防止同时多个线程创建多个对象就需要考虑到线程安全的问题。

方式一:

给getInstance()添加synchronized符号

public class BankTest {
    static Bank b1=null;
    static Bank b2=null;
    public static void main(String[] args) {
        Thread t1=new Thread(){
            @Override
            public void run() {
                b1=Bank.getInstance();
            }
        };
        Thread t2=new Thread(){
            @Override
            public void run() {
                b2=Bank.getInstance();
            }
        };
        t1.start();
        t2.start();
        //注意这里加一个睡眠,mian线程直接向下执行输出时b1、b2还没造好,等造好后再输出地址
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b1==b2);
    }
}
class Bank{
    static Bank a1=null;
    private Bank(){
    }
    //给get方法加上synchronized就可以了
    public static synchronized Bank getInstance(){
        if(a1==null){
            a1=new Bank();
        }
        return a1;
    }
}

方式二:

同步代码块
给getInstance内的方法内容加上synchronized

public class BankTest {
    static Bank b1=null;
    static Bank b2=null;
    public static void main(String[] args) {
        Thread t1=new Thread(){
            @Override
            public void run() {
                b1=Bank.getInstance();
            }
        };
        Thread t2=new Thread(){
            @Override
            public void run() {
                b2=Bank.getInstance();
            }
        };
        t1.start();
        t2.start();
        //注意这里加一个睡眠,mian线程直接向下执行输出时b1、b2还没造好,等造好后再输出地址
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b1==b2);

    }
}
class Bank{
    static Bank a1=null;
    private Bank(){
    }
    //给get方法加上synchronized就可以了
    public static Bank getInstance(){
        synchronized (Bank.class){
            if(a1==null){
                a1=new Bank();
            }
            return a1;
        }
    }
}

方式三:

首先考虑instance是否存在,在实例有对象的情况下直接就可以调用它,不需要每个线程进入同步代码块再创建对象,节约时间
存在指令重排问题,需要将instance声明为volatile

public class BankTest {
    static Bank b1=null;
    static Bank b2=null;
    public static void main(String[] args) {
        Thread t1=new Thread(){
            @Override
            public void run() {
                b1=Bank.getInstance();
            }
        };
        Thread t2=new Thread(){
            @Override
            public void run() {
                b2=Bank.getInstance();
            }
        };
        t1.start();
        t2.start();
        //注意这里加一个睡眠,mian线程直接向下执行输出时b1、b2还没造好,等造好后再输出地址
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b1==b2);

    }
}
class Bank{
    static Bank a1=null;
    private Bank(){
    }
    //给get方法加上synchronized就可以了
    public static Bank getInstance(){
        if(a1==null){
            synchronized (Bank.class){
                if(a1==null){
                    a1=new Bank();
                }
            }
        }
        return a1;
    }
}

版权所有:伸手党盘
文章标题:线程安全的懒汉模式
文章链接:https://ssdpan.cn/?post=364
本站文章来源于网络搜集和原创,仅供学习使用,未经授权请勿用于任何商业用途,如有侵权及时联系删除

推荐阅读:


扫描二维码,在手机上阅读