单例模式下,解决并发问题

目录

最终解决方案

探讨为何这么写?


最终解决方案

双重检查加锁
首先检查是否实例已经创建了,如果尚未创建,才进行同步。这样一来,只有第一次会同步

public class SnowFlakeGenerateIDUtils {
	public volatile static SnowFlakeGenerateIDUtils snowWork = null;
	public static String getSnowId() {
        //单例,解决并发问题
        if (snowWork == null) {
            synchronized (SnowFlakeGenerateIDUtils.class) {
                if (snowWork == null) {
                    snowWork = new SnowFlakeGenerateIDUtils(currentWorkerId, currentDatacenterId, currentSequence);
                }
            }
        }
        Long nextId = snowWork.nextId();
        return nextId.toString();
    }
	
}

注意的点:

  1. 对象需要用volatile关键字修饰
  2. 锁用的是单例对象 synchronized (SnowFlakeGenerateIDUtils.class)

 

 

探讨为何这么写?

先来看一段代码

private Singleton() {}

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

这段逻辑,在单线程的程序中工作得很好。但是,当引入多线程时,就可能会出现问题。

个人理解:当一个线程正在执行对象初始化,同事另一个对象也进来,发现对象并没有初始化,也执行初始化。就会存在并发下被覆盖的问题。

引出Volatile
Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。则上面对象初始化操作针对不同线程不可见的问题就解决了。

 

 

除了这种解决方式,当然还有其他的,可参考:

https://blog.csdn.net/qq_36704549/article/details/104521878

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值