type
status
date
slug
summary
tags
category
icon
password
这里写文章的前言:
一个简单的开头,简述这篇文章讨论的问题、目标、人物、背景是什么?并简述你给出的答案。
可以说说你的故事:阻碍、努力、结果成果,意外与转折。
📝 介绍
锁在并发处理中占据一席之地,但是使用锁有一个不好的地方,就是当一个线程没有获取到锁的时候会被阻塞挂起来,这会导致线程上下文的切换和重新调度开销。
java提供了非阻塞volatile关键字来解决共享变量的可见性问题,这在一定程度上弥补了锁带来的开销问题,但是volatile只能保证共享可见的问题,不能解决读一改一写的原子性问题。CAS即CompareAndSwap(比较交换),即是JDK提供非阻塞原子性操作
CAS机制
它包含3个参数CAS(V,E,N),V表示要更新变量的值,E表示预期值,N表示新值。仅当V值等于E值的时候,才会将V的值设置为N;如该V与E的值不一样,则说明已经有其他线程做了更新,则当前线程什么都做不了。最后,CAS返回当前V的真实值
比如看:AtomicInteger#getAndIncrement 的方法
最后调用到 Unsafe 类中
var1: AtomicInteger 这个对象a
var2: 偏移量(有效地址值)
var5: AtomicInteger 这个对象a在地址var2上的期待的值
var5 +var4: 是值操作 + 1
底层原理
接着上面的跟进,compareAndSwapInt方法:
var1: 操作对象
var2: 操作对象a的地址偏移量,有效地址
var4: 我们期待这个a是什么值
var5: 表示a的实际值
再往下跟,C语言的代码
首先使用 jint 计算了 value 的地址值,然后根据这个地址,使用了 Atomic 的 cmpxchg 方法进行比较交换。将问题抛给了 cmpxchg
cmpxchg函数代码:
现在不同操作系统下会调用不同的 cmpxchg 重载函数
再往下跟
move 指令表示是将后面的值移动到前面的寄存器上,然后调用 LOCK_IF_MP 和 下面的 cmpxchg 汇编指令进行了比较交换。
cas指令最终由操作系统汇编指令完成
CAS优缺点
优点
cas是一种乐观锁,而且还是非阻塞的轻量级的乐观锁。
一个线程想要获取锁,对方会给一个回应表示这个锁能不能获得。
在资源竞争不激烈的情况下性能高,相对 synchronized 重量锁,synchronized会进行比较复杂的加锁,解锁和唤醒操作
缺点
缺点也是一个非常重要的知识点,因为涉及到了一个非常著名的问题,叫做ABA问题。假设一个变量 A ,修改为 B之后又修改为 A,CAS 的机制是无法察觉的,但实际上已经被修改过了。这就是ABA问题,
ABA问题会带来大量的问题,比如说数据不一致的问题等等。我们可以举一个例子来解释说明。
你有一瓶水放在桌子上,别人把这瓶水喝完了,然后重新倒上去。你再去喝的时候发现水还是跟之前一样,就误以为是刚刚那杯水。如果你知道了真相,那是别人用过了你还会再用吗
🤗 总结归纳s
📎 参考文章
有关文章的问题,欢迎您在底部评论区留言,一起交流~