如何实现一个线程安全的数据结构

1、饿汉模式
public class Singletan {

    private static Singletan instance = new Singletan();
    
    public Singletan(){}
    
    public static Singletan getInstance() {
        return instance;
    }
}
2、静态内部类

较上面有所优化,就是使用了lazy-loading。Singletan类被加载,但是instance并没有立即初始化,只有调用getInstance方法时才会初始化。

//加载内部类SingletanHolder,从而实例化instance
public class Singletan {

    private static class SingletanHolder {
        private static final Singletan INSTANCE = new Singletan();
    }
    
    public Singletan(){}
    
    public static final Singletan getInstance() {
        return SingletanHolder.INSTANCE;
    }
}
3、CAS:Compare and Swap(比较和交换)
  • 乐观锁,无锁算法。CAS有3个参数:内存值V、旧值A、要修改的新值B,当且仅当旧值 A 和内存值 V 相同时,才将内存值 V 修改为 B,否则会尝试重新获取 V 的当前值,重新比较。
  • 优点:没有线程切换和阻塞的额外开销,支持较大并行度。
  • 缺点:①在并发量较高时,如果许多线程反复尝试去更新一个变量,却又一直更新失败,会消耗很多CPU资源。②银行取款 ABA 问题,所以不仅要比较旧值和内存值,还要比较变量的版本号是否一致,只有一致才进行操作。

银行取款ABA问题:假如账户开始有100元,在取款机上取走50,取款机出现问题一共提交了两次请求(线程1,线程2),第二次请求(线程2)在执行时因为某种原因被阻塞了,这时候有人往你的账户打了50元,线程2恢复了可执行状态,这个时候就会出现问题,原本线程2应该执行失败的,但是比较后仍然与旧值一致,这样就造成了账户实际上扣款了两次!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值