多线程案例

单例模式

这是一种常见的“设计模式”,当在某些情况下,不需要多个实例,就可以使用单例模式来解决,如果想要尝试创建多个实例,代码就会报错。

可以有两种方式:
饿汉模式:当类加载的时候就会立刻实例化。
懒汉模式:类加载时不会实例化,当第一次调用这个类的时候才会去实例化。(可以仔细拼一下为啥叫这两个名字,一个急得想马上创建,一个等啊等啊不到万不得已需要使用了才实例化)

饿汉模式

类加载的时候就会立刻实例化

static class Singleton{
   
        //这里的构造方法使用private,在类外就无法new这个实例了
        private Singleton() {
   
        }

        //这里使用static,表示和实例无关,只与类有关
        private static Singleton instance = new Singleton();
        //gerInstance是获取实例的唯一方法
        public static Singleton gerInstance() {
   
            return instance;
        }
    }

    public static void main(String[] args) {
   
        Singleton s1 = Singleton.gerInstance();
        Singleton s2 = Singleton.gerInstance();
        System.out.println(s1 == s2);
    }

在main方法中,看起来是创建了两个实例,但是我们的打印结果是true,说明这两个实例其实是一个。

懒汉模式

类加载的时候不会实例,只有在第一次调用这个类的时候才会去实例化

static class Singleton {
   
        private Singleton() {
   
        }

        private static Singleton instance = null;
        public static Singleton getInstance() {
   
            if(instance == null) {
   
                instance = new Singleton();
            }
            return instance;
        }
    }

可以观察一下这个代码,当多线程同时调用getInstance方法时,是需要分成几步的。读取instance中的内容,判断是否为null,如果为null,就new实例。返回实例的地址。根据线程安全的思想,可以看出这个代码会导致线程不安全。

1、给getInstance加锁,保证原子性

static class Singleton {
   
        private Singleton() {
   
        }

        private static Singleton instance = null;
        public static Singleton getInstance() {
   //也可以把锁加在这一行,只不过是锁粒度大一点
            synchronized (Singleton.class) {
   
                if(instance == null) {
   
                    instance = new Singleton();
                }
            }
            return instance;
        }
    }

仔细分析,可以发现,如果把实例化已经创建好之后,再去调用getInstance就属于线程安全了。只有在实例化之前是线程不安全的。就可以只在实例化之前加锁,实例化之后就可以不用加锁了,这样就降低了锁的粒度

2、再次进行判断,降低锁粒度

static class Singleton {
   
        private Singleton() {
   
        }

        private static Singleton instance = null;
        public static Singleton getInstance() {
   //也可以把锁加在这一行,只不过是锁粒度大一点
            if (instance == null) {
   //这个判断是为了只在实例化之前调用加锁,降低锁的粒度
                synchronized (Singleton.class) {
   
                    if(instance == null) {
   
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }

这个代码还存在一点线程不安全的问题,多线程在调用getInstance,先加锁的线程在修改instance,而后加锁的线程在读数据,这样就会存在内存可见性的安全问题

3、加上volatile,解决内存可见行的问题。

static class Singleton {
   
        private Singleton()</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值