关于 volatile 关键字只保证了内存可见性而不原子性 && volatile + CAS 算法保证原子性

1.volatile 关键字值保证了内存可见性而不原子性

内存可见性指的是   共享变量 X 在线程A中修改之后,在其他线程中的数据副本全部失效,其他线程需要使用该变量的时候,需要去主内存重新的刷新获取最新的值。volatile 修饰变量之后,可以达到这个要求。

但是  如果针对volatile的一些操作,比如 自增操作。分为了  load   修改   store  三步。汇编指令级别有四步,第四步是加上 一个  内存屏障,避免 指令的重排序规则。

但是在  这三步中,是非线程安全的,在还没有将 store 指令操作完成的时候,如果有其他的线程介入修改 共享变量并更新,此时的值是错误更新的。

在线程 A store 之前 ,B读到 X = 100, 并且store更新 为101,但是A 已经读到了 100(内存可见性已经晚了,是针对执行load操作的时候,需要刷新读取最新的值),store 101。 此时两次自增操作,得到的结果是101,是错误的。(问题在于:如果多个线程对同一个共享变量进行操作,存在资源抢占的问题,结果可能会来回的不断覆盖,每次结果都不同。)

所以可以保证内存可见性,但是无法 原子性。

 

2.volatile + CAS 算法保证原子性

还是上面的例子:

自增操作:

<
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我将回答你的问题。首先,Java中的ReentrantLock是一种可重入的互斥锁,它的底层实现依赖于CAS(Compare and Swap,比较并交换)算法和AQS(AbstractQueuedSynchronizer,抽象队列同步器)框架。CAS算法是一种无锁算法,在Java中通过sun.misc.Unsafe类来实现。它利用CPU底层的原子指令完成对内存中的数据进行原子性操作,保证了数据的一致。而AQS框架则是一种实现锁、信号量等同步操作的基础框架,主要通过 FIFO 队列实现等待机制,同时提供了公平锁和非公平锁两种实现方式。 Java内存是一种抽象的概念,它定义了各种线程在何时、何地和如何访问共享内存。Java内存通过保证原子性、可见和有序保证线程之间的并发执行正确。其中原子性是指操作的不可分割,比如对于32位的数据,它们必须被一次地读取或写入,不能被分解成两个16位的操作。可见是指对于共享变量的修改对于其他线程来说是可见的,主要通过volatile关键字和synchronized关键字保证。有序是指执行顺序必须满足一定规则,比如一个事件在发生前必须先发生另一个事件。 Java线程池是一种可以提高程序能的技术,在Java中通过ThreadPoolExecutor类来实现。它主要包括核心线程池、任务队列、最大线程池、线程工厂和拒绝策略等几个部分。其中核心线程池和最大线程池决定了线程池的线程数量,任务队列决定了线程池中的任务调度策略,线程工厂则决定了线程池中线程的创建方式,而拒绝策略则是当任务队列已经满了且线程池中的线程已被占用时,如何处理新的任务请求。 最后来回答你的问题:volatile关键字是一种Java线程间的同步机制,它保证一个变量在多个线程之间的可见,也能保证一定程度的指令重排序。当一个变量被声明为volatile后,所有线程都能看到这个变量的最新值,而不管这个变量是否在本地CPU缓存中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值