volatile为什么不保证原子性?为什么Atomic保证原子性?

2022-07-31,,,

volatile

  • 前言
  • 举个栗子
  • 原因
    • 错误理解 (不想看就跳过)
    • 真正原因
  • 解决措施
  • 为什么AtomicXXX保证原子

前言

大家都知道,volatile是具有可见性的。即是在多线程操作下,volatile修饰的共享变量会在更新操作之后,每个线程获得最新的值。
不了解volatile的实现原理可以参考:博客链接

那么问题来了,既然可以保证修改后的变量可以被立即更新,那么为什么不能保证操作的原子性呢?

举个栗子

private volatile int i = 0;
i++;

如果在多线程操作下,i++调用10次,那么i的值会是10吗?答案是小于10的,因为会有操作被覆盖。

原因

i++的操作是分三步实现的。

  1. 线程获取 i 的值
  2. temp = i+1
  3. i = temp(写回主存)

错误理解 (不想看就跳过)

如果此时i的值是5,此时线程A获取了 i 的值,并且执行到了第二步。然后线程A阻塞,轮到线程B执行。B执行同样的操作,获取到 i = 5,然后执行自增操作并且写回主存(此时i = 6)。然后轮到线程A执行将自增完成的 i 值(i = 6)写回主存。

这样,虽然进行了两次自增,但是 i 的值只增加了一次,不具备原子性。

( 更新完变量后写回主存不是立即执行的,这个时候如果对volatile变量执行操作,保证不了原子性)虽然我很想这样说,但是这个是错误的理解

因为assign store write这三个原子指令是连续的。也就是说,volatile修饰的变量被修改完成之后,会被立即写回主存,其他变量可以立即看到新值。(图片来自尚硅谷)

真正原因

根据缓存一致性,一个处理器的缓存回写到主存会导致其他处理器的缓存失效。当线程A,B同时执行volatile int i的自增的时候,先执行完的线程A回写数据到主存,导致B的缓存变量无效(因此执行+1操作已经没有意义),直接从主存读取最新的值,这样就相当于少做了一次+1。

自称从美团并发构架师的人那学来的无敌图(但是被我偷了)@博主void丿

解决措施

1.使用总线锁保证原子性

所谓总线锁就是使用处理器提供一个LOCK#信号,当一个处理器在总线输出此信号的时候,其他处理器将被阻塞,该处理器独共享内存

2.使用缓存锁保证原子性

在同一时刻只需要保证某个内存地址的操作是原子性即可。

3.如果是int类型 i++这样的自增操作,直接使用AtomicInteger(保证原子性)

为什么AtomicXXX保证原子性

Atomic使用了volatile修饰value,然后一直使用CAS保证原子性。(其实还用到了native)
看一下Atomicxxx的源码,这里是AtomicLong

public class AtomicLongextends Numberimplements java.io.Serializable {
    private volatile long value;
 
    /**
     * Creates a new AtomicLong with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicLong(long initialValue) {
        value = initialValue;
    }
 
    /**
     * Creates a new AtomicLong with initial value {@code 0}.
     */
    public AtomicLong() {
    }

其中value是用volatile修饰的

CAS源码

int compare_and_swap (int* reg, int oldval,int newval)
{
  ATOMIC();
  int old_reg_val = *reg;
  if (old_reg_val == oldval) 
     *reg = newval;
  END_ATOMIC();
  return old_reg_val;
}

CAS是乐观锁,如果发现寄存器旧值发生了改变,说明有CPU在修改,重新进行这次操作。用CAS一直判断 就可以保证随时获得最新的值,保证操作的原子性。

都看到这里了,还不点个赞支持支持吗 (ノへ ̄、)

本文地址:https://blog.csdn.net/glum_0111/article/details/107672828

《volatile为什么不保证原子性?为什么Atomic保证原子性?.doc》

下载本文的Word格式文档,以方便收藏与打印。