CAS模型的问题

其中在java中使用CAS底层借助 Unsafe 来操作,实现非阻塞的修改变量值,CAS是使用了硬件指令保证原子性
每次进行compareAndSwap方法时,需要cas有3个参数
内存地址V,
旧的预期值E,
要修改的新值N

当 E == V 时,修改 V 值为 N,返回true
当 E != V 时,修改失败,返回false
AtomicBoolean,AtomicInteger,AtomicLong 等都是使用CAS来实现的。但是没有解决ABA问题。

什么是ABA问题

一个线程获取值为a,另一个线程将数值由a改成了b,接着又改成了a,此时线程b的CAS操作认为是没有变化,但其实已经变化过了,这种过程就叫ABA问题。

CAS的ABA问题解决

、ABA问题

> 解决方法:JAVA中提供了AtomicStampedRefernce/AtomicMarkableReference来处理会发生

ABA问题的场景,主要是在对象中额外再增加一个标记来标识对象是否有过变更。

2、CAS应用场景隐含竞争是短暂的,否则不断的自旋尝试会过度消耗CPU> 解决方法加入超时设置

3、CAS只能保证一个共享变量的原子操作,解决方法是使用锁或者合并多个变量> AtomicReference提供了以无锁方式访问共享资源的能力

CAS的总结

AtomicInteger、AtomicBoolean、AtomicLong、AtomicReference这些原子类型,它们无一例外都采用了基于volatile 关键字 +CAS 算法无锁的操作方式来确保共享数据在多线程操作下的线程安全性。- volatile关键字保证了线程间的可见性,当某线程操作了被volatile关键字修饰的变量,其他线程可以立即看到该共享变量的变化。

- CAS算法,即对比交换算法,是由UNSAFE提供的,实质上是通过操作CPU指令来得到保证的。CAS算法提供了一种快速失败的方式,当某线程修改已经被改变的数据时会快速失败。

- 当CAS算法对共享数据操作失败时,因为有自旋算法的加持,对共享数据的更新终究会得到计算。总之,原子类型用自旋+CAS的无锁操作保证了共享变量的线程安全性和原子性。

AQS模型

AbstractQueuedSynchronizer抽象队列同步器:AQS是JDK下提供的一套用于实现基于FIFO等待队列的阻塞锁

和相关的同步器的一个同步框架。AQS维护了一个volatile int state(代表共享资源)和一个FIFO线程等待

队列(多线程争用资源被阻塞时会进入此队列)

抽象队列同步器中包括两个部分:临时资源和一个FIFO的CLH阻塞队列.

AQS的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资

源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,

这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。

内部使用AQS的例子:以ReentrantLock为例,state初始化为0,表示未锁定状态。A线程lock()时,会调用

tryAcquire()独占该锁并将state+1。此后,其他线程再tryAcquire()时就会失败,直到A线程unlock()到

state=0(即释放锁)为止,其它线程才有机会获取该锁。当然,释放锁之前,A线程自己是可以重复获取此锁

的(state会累加),这就是可重入的概念。但要注意,获取多少次就要释放多么次,这样才能保证state是能

回到零态的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值