写点什么

高并发中的 atomic

作者:Steven
  • 2023-01-10
    河南
  • 本文字数:794 字

    阅读完需:约 3 分钟

CAS 原理

对于并发控制而言,锁是一种悲观策略,会阻塞线程执行。而无锁是一种乐观策略,它会假设对资源的访问时没有冲突的,既然没有冲突就不需要等待,线程不需要阻塞

CAS 方法包含三个参数 CAS(V,E,N):内存位置(V),预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器将会自动将该位置值更新为新值,否则,不做任何操作。如果 V 的值不等于 E,说明已经被其他线程修改了,当前线程可以放弃此操作,也可以再次尝试次操作直至修改成功。

public final int getAndSet(int newValue) { for (;;) { int current = get(); if (compareAndSet(current, newValue)) return


public final int getAndSet(int newValue) { for (;;) { int current = get(); if (compareAndSet(current, newValue)) return


复制代码


public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }
复制代码

在 AtomicInteger 的源码中,可以看到 compareAndSet 只有预期和更新两个入参,而该类的成员 value 被加上了 Volatile 关键字

Unsafe 类是 CAS 实现的核心。

现在的 CPU 都支持“读-比较-修改”的原子操作,也就是一个 cpu 在执行这个操作的时候,绝对不会被其他线程中断。在多 CPU 的情况下,volatile 保证了线程可以及时发现临界区的修改。


Atomic 包:假如想实现一个功能来统计网页访问量,可以用 count++ 来统计访问量,但是这个自增操作不是线程安全的。

count++ 可以分成三个操作:

  1. 获取变量当前值

  2. 给获取的当前变量值+1

  3. 写回新的值到变量

  • 并发中的问题


    假如 count 的值目前是 10,线程 A 和线程 B 都进行了操作 1,即取到了 count=10 的值,


    接下来同时进行操作 2,


    但是 A 先进行到操作 3,count 现在值为 11。


    但是因为 B 一开始取出的 count 的值也是 10,所以 B 执行到操作 3 后,count 的值依然是 11。

在 java.util.concurrent 包下可以使用 AtomicInteger 来保证线程安全。

发布于: 刚刚阅读数: 5
用户头像

Steven

关注

还未添加个人签名 2023-01-09 加入

还未添加个人简介

评论

发布
暂无评论
高并发中的atomic_Steven_InfoQ写作社区