原子变量、无锁算法和非阻塞机制

原子变量

锁使用起来比较方法,但是它存在一些问题:

  • 性能问题。尽管现代JVM对于锁进行了很多优化,但是在多线程下,线程上下文切换仍需要os的支持,这部分开销始终是无法避免的。在计算任务比较断的时候,线程上下文切换将占据极大的部分,发生激烈的竞争,影响性能。换句话来说,锁太重了。
  • 活跃性问题。一个线程失败,可能引起所有线程阻塞。

volatile显然是一种非常轻量的同步操作,它不会引起上下文切换,但它无法支持复合操作,例如i++,看起来是一条指令,实际上是三条字节码指令。所以它也无法支持“测试并更新”这种在并发世界里极为重要但复合操作。

有没有一种粒度更细,类似于volatile,又支持原子更新操作的机制呢?

原子变量运而生。它是对于常规变量的一种封装,利用底层native接口,提供了变量上的原子一系列复合操作,例如i++,CAS等。具体参考CAS和原子类。原子变量本质上是用硬件实现的“测试和更新”复合原子操作,并且,在大量精巧的非阻塞并发程序中,核心就是将一致性问题一步步缩小范围到某一组原子变量上面。

非阻塞算法设计

如果在算法的每个步骤中都存在某个线程能够执行下去,这种算法就被称为无锁(Lock-Free)算法。

不管是非阻塞算法还是无锁算法,都是针对锁的活跃性问题衍生出来的概念。这种算法通常比锁更难设计,核心就是将一致性问题一步步缩小范围到某一组原子变量上面。
那么,如何利用原理变量设计更好的非阻塞机制呢?我们来看一些案例。

非阻塞计数器:

@ThreadSafe
public class CasCounter {
   
    private SimulatedCAS value;

    public int getValue() {
   
        return value.get();
    }

    public int increment() {
   
        int v;
        do{
   
            v = value.get();
        // CAS更新,避免更新丢失
        } while (v != value.compareAndSwap(v, v + 1));
        return v + 1;
    }
}

维持复合不变性条件(涉及多个变量):

  • 代码中必须保证lower<upper
  • 由于涉及到两个变量,两个变量必须同时更新
  • 防止丢失修改,采用CAS
public class CasNumberRange {
   
    // 1. 保证复合不变性条件,lower和upper必须作为一个整体更新
    @Immutable
    private static class IntPair {
   
        final int lower; // Invariant: lower <= upper
        final int upper;

    }

    private final AtomicReference<IntPair> values = new AtomicReference<IntPair>(new IntPair(0, 0));

    public int getLower() {
   
        return values.get().lower;
    }

    public int getUpper() {
   
        return values.get().upper;
    }

    public void setLower(int i) {
   
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值