美团终面:你确定CAS不加锁吗?

开发 前端
我们以Java.util.concurrent中的AtomicInteger为例,看一下在不使用锁的情况下是如何保证线程安全的。主要理解getAndIncrement方法,该方法的作用相当于 ++i 操作。

CAS大家都知道,这是一项乐观锁技术,是Compare And Swap的简称,顾名思义就是先比较再替换。

虽然他叫乐观锁,但是我们都知道它是不需要加锁的,在JDK1.5 中的JUC就是建立在CAS之上的。相对于synchronized这种阻塞算法,CAS是非阻塞算法的一种常见实现。所以J.U.C在性能上有了很大的提升。

我们以java.util.concurrent中的AtomicInteger为例,看一下在不使用锁的情况下是如何保证线程安全的。主要理解getAndIncrement方法,该方法的作用相当于 ++i 操作:

public class AtomicInteger extends Number implements java.io.Serializable {  
private volatile int value;
public final int get() {
return value;
}
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
}

getAndIncrement采用了CAS操作,每次从内存中读取数据然后将此数据和+1后的结果进行CAS操作,如果成功就返回结果,否则重试直到成功为止。而compareAndSet利用unsafe的compareAndSwapInt方法实现的。

啥是Unsafe呢?

Unsafe是CAS的核心类。因为Java无法直接访问底层操作系统,而是通过本地(native)方法来访问。不过尽管如此,JVM还是开了一个后门,JDK中有一个类Unsafe,它提供了硬件级别的原子操作。

Unsafe是Java中一个底层类,包含了很多基础的操作,比如数组操作、对象操作、内存操作、CAS操作、线程(park)操作、栅栏(Fence)操作,JUC包、一些三方框架都使用Unsafe类来保证并发安全。

Unsafe类提供了硬件级别的原子操作,如CAS原子操作。

​但是,大家有没有想过这样的问题:

硬件层面CAS又是如何保证原子性的呢?真的完全没加锁吗?

拿比较常见的x86架构的CPU来说,其实 CAS 操作通常使用 cmpxchg 指令实现的。

可是为啥cmpxchg 指令能保证原子性呢?主要是有以下几个方面的保障:

1.  cmpxchg 指令是一条原子指令。在 CPU 执行 cmpxchg 指令时,处理器会自动锁定总线,防止其他 CPU 访问共享变量,然后执行比较和交换操作,最后释放总线。

2.  cmpxchg 指令在执行期间,CPU 会自动禁止中断。这样可以确保 CAS 操作的原子性,避免中断或其他干扰对操作的影响。

3.  cmpxchg 指令是硬件实现的,可以保证其原子性和正确性。CPU 中的硬件电路确保了 cmpxchg 指令的正确执行,以及对共享变量的访问是原子的。

所以,在操作系统层面,CAS还是会加锁的,通过加锁的方式锁定总线,避免其他CPU访问共享变量。

所以,解决并发问题,归根结底还得靠锁!

责任编辑:姜华 来源: Hollis
相关推荐

2024-05-27 11:35:40

2024-04-01 00:00:00

Redis缓存服务消息队列

2024-04-22 00:00:00

CASCPU硬件

2024-10-31 08:50:14

2017-06-02 08:48:29

互斥锁JavaCAS

2022-08-27 13:50:44

TCP服务端函数

2022-09-12 15:55:57

TCP函数程序

2024-09-18 09:02:14

单核服务器线程切换

2023-04-21 13:57:38

Redis阻塞半自动

2024-04-24 09:02:58

线程池面试锁升级

2023-04-03 07:57:00

2021-09-09 19:08:49

JDK版本Java

2023-04-03 10:24:00

spring事务场景

2022-09-08 13:56:49

MySQL事务记录锁

2015-10-19 09:57:02

阿里美团大众

2023-07-13 09:16:47

循环队列指针front​

2024-04-15 08:37:35

2022-08-24 07:44:53

流量系统数据

2023-07-27 07:28:04

存储链表HashSet

2021-08-29 18:36:17

MySQL技术面试题
点赞
收藏

51CTO技术栈公众号