非阻塞同步机制和CAS

简介: 非阻塞同步机制和CAS

目录



非阻塞同步机制和CAS


我们知道在java 5之前同步是通过Synchronized关键字来实现的,在java 5之后,java.util.concurrent包里面添加了很多性能更加强大的同步类。这些强大的类中很多都实现了非阻塞的同步机制从而帮助其提升性能。


什么是非阻塞同步


非阻塞同步的意思是多个线程在竞争相同的数据时候不会发生阻塞,从而能够在更加细粒度的维度上进行协调,从而极大的减少线程调度的开销,从而提升效率。非阻塞算法不存在锁的机制也就不存在死锁的问题。


在基于锁的算法中,如果一个线程持有了锁,那么其他的线程将无法进行下去。使用锁虽然可以保证对资源的一致性访问,但是在挂起和恢复线程的执行过程中存在非常大的开销,如果锁上面存在着大量的竞争,那么有可能调度开销比实际工作开销还要高。


悲观锁和乐观锁


我们知道独占锁是一个悲观锁,悲观锁的意思就是假设最坏的情况,如果你不锁定该资源,那么就有其他的线程会修改该资源。悲观锁虽然可以保证任务的顺利执行,但是效率不高。


乐观锁就是假设其他的线程不会更改要处理的资源,但是我们在更新资源的时候需要判断该资源是否被别的线程所更改。如果被更改那么更新失败,我们可以重试,如果没有被更改,那么更新成功。


使用乐观锁的前提是假设大多数时间系统对资源的更新是不会产生冲突的。


乐观锁的原子性比较和更新操作,一般都是由底层的硬件支持的。


CAS


大多数的处理器都实现了一个CAS指令(compare and swap),通常来说一个CAS接收三个参数,数据的现值V,进行比较的值A,准备写入的值B。只有当V和A相等的时候,才会写入B。无论是否写入成功,都会返回V。翻译过来就是“我认为V现在的值是A,如果是那么将V的值更新为B,否则不修改V的值,并告诉我现在V的值是多少。”


这就是CAS的含义,JDK中的并发类是通过使用Unsafe类来使用CAS的,我们可以自己构建一个并发类,如下所示:


public class CasCounter {
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;
    private volatile int value;
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                    (CasCounter.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    public CasCounter(int initialValue) {
        value = initialValue;
    }
    public CasCounter() {
    }
    public final int get() {
        return value;
    }
    public final void set(int newValue) {
        value = newValue;
    }
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
}


上面的例子中,我们定义了一个原子操作compareAndSet, 它内部调用了unsafe的compareAndSwapInt方法。


看起来上面的CAS使用比直接使用锁复杂,但实际上在JVM中实现锁定时需要遍历JVM中一条非常复杂的代码路径,并可能导致操作系统级的锁定,线程挂机和上下文切换等操作。在最好的情况下,锁定需要执行一次CAS命令。


CAS的主要缺点就是需要调用者自己来处理竞争问题(重试,回退,放弃),而在锁中可以自动处理这些问题。


前面的文章我们也讲到了原子变量,原子变量的底层就是使用CAS。


本文的例子请参考https://github.com/ddean2009/learn-java-concurrency/tree/master/CAS

相关文章
|
机器学习/深度学习 算法 关系型数据库
【顶级EI完美复现】电力系统碳排放流的计算方法【IEEE 14节点】(Matlab代码实现)
【顶级EI完美复现】电力系统碳排放流的计算方法【IEEE 14节点】(Matlab代码实现)
890 0
|
存储 SQL 关系型数据库
【MySQL基础篇】MySQL约束语法
文章介绍了MySQL中表的约束概念,包括非空、唯一、主键、默认和外键约束,以及如何在创建和修改表时指定这些约束。外键约束用于保持数据的一致性和完整性,文章通过示例展示了添加、删除外键的语法,并讨论了不同的删除/更新行为,如CASCADE和SETNULL。
【MySQL基础篇】MySQL约束语法
|
存储 数据安全/隐私保护 计算机视觉
Python教程:一文了解从Bytes到Bits的数据转换
在Python编程中,处理数据时经常需要在字节(bytes)和位(bits)之间进行转换。这种转换在网络通信、数据加密、图像处理等领域尤为常见。本文将详细介绍如何在Python中进行字节与位之间的转换,并提供一个实用的功能:如何在指定的位位置替换位数据。
3753 4
|
移动开发 小程序 前端开发
uniap开发微信小程序如何在线预览pdf文件
这是一段关于在线预览和处理PDF的多方案说明,包括使用JavaScript库PDF.js(如`pdfh5.js`)实现H5页面预览,提供QQ群和技术博客链接以获取帮助和支持。还介绍了两个适用于Uni-app的插件,一个用于H5、小程序和App中的PDF预览和下载,另一个专门解决手机端PDF预览问题。此外,还详细描述了在Uni-app中使用微信小程序API`wx.openDocument`显示PDF的步骤,包括上传文件、配置权限和编写代码。
|
缓存 NoSQL Redis
Redis 解决缓存雪崩 缓存穿透 缓存击穿(Redis使用必看)(1)
Redis 解决缓存雪崩 缓存穿透 缓存击穿(Redis使用必看)(1)
|
Android开发 iOS开发 容器
CocosCreator3.8研究笔记(十九)CocosCreator UI组件(三)(2)
CocosCreator3.8研究笔记(十九)CocosCreator UI组件(三)
1695 0
怎样去掉list里重复的数据(多种方法)
怎样去掉list里重复的数据(多种方法)
456 0
怎样去掉list里重复的数据(多种方法)
|
新零售 达摩院
(5000字长文)阿里巴巴“新六脉神剑”前瞻:从授人鱼到授人渔
(5000字长文)阿里巴巴“新六脉神剑”前瞻:从授人鱼到授人渔
1343 0
(5000字长文)阿里巴巴“新六脉神剑”前瞻:从授人鱼到授人渔
|
编解码
何必冥思苦想,直播app开发中延迟的“罪魁祸首”在这
关注直播系统开发的朋友都知道,直播APP开发中的流媒体传输一般流程是采集、前处理、压缩、推流、拉流、解码、播放,这当中每个阶段都是十分重要的,所以为了保证用户观看的及时性,这些流程需要高度协调统一,来减少在线直播的延迟,那么还有那些方面是延迟的影响因素呢?
何必冥思苦想,直播app开发中延迟的“罪魁祸首”在这

热门文章

最新文章