Java concurrent program - Java无锁初探

1.CAS与volatile

compareAndSet,它的简称就是CAS。其原理如下:
在这里插入图片描述
在这里插入图片描述
获取共享变量时,为了保证该变量的可见性,需要使用volatile修饰。
它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作volatile变量都是直接操作主存。即一个线程对 volatile 变量的修改,对另一个线程可见。
volatile 仅仅保证了共享变量的可见性,让其它线程能够看到最新值,但不能解决指令交错问题(不能保证原子性)。
CAS 必须借助volatile才能读取到共享变量的最新值来实现“比较并交换”的效果。
CAS的特点:

  • 结合CAS和volatile可以实现无锁并发,适用于线程数少、多核CPU的场景下。
  • CAS是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量。
  • synchronized是基于悲观锁的思想:最悲观的估计,得防着其它线程来修改共享变量。
  • CAS 体现的是无锁并发、无阻塞并发。因为没有使用 synchronized,所以线程不会陷入阻塞,这是效率提升的因素之一。

2.原子整数

J.U.C并发包提供了:AtomicBoolean、AtomicInteger、AtomicLong。
其中AtomicInteger有以下重要方法:
AtomicInteger i = new AtomicInteger(0);
getAndIncrement()返回0,但i = 1。
incrementAndGet()返回1,但i = 1。
getAndAdd(5)返回0,但i = 5。
addAndGet(5)返回5,但i = 5。
getAndUpdate(p -> p - 2) 返回0,但i = -2。
updateAndGet(p -> p + 2) 返回2,但i = 2。getAndUpdate()和updateAndGet()可以用与加减乘除只需要修改lambda表达式即可。
updateAndGet()的原理如下:
在这里插入图片描述

3.原子引用

除去基本类型,还有引用类型。使用原子引用可以保证其原子性。原子引用类型:AtomicReference、AtomicMarkableReference和AtomicStampedReference。AtomicReference可以通过泛型来确定保护的对象。
ABA问题:
初始变量为A。在CAS之前,其他线程把共享变量改为了B,另一个线程又把B改为了A,CAS无法感知共享变量是否被其他线程修改过,CAS只能判断共享变量是否与最初值相同。
AtomicStampedReference和AtomicMarkableReference
AtomicStampedReference通过给共享变量加了版本号,来判断共享变量是否被修改过,如果修改过,CAS就会失败。AtomicMarkableReference,并不关心引用变量更改了几次,只是单纯的关心是否更改过。

4.原子数组

常用的原子数组有:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。用于保护数组内元素的线程安全。用法和原子整数类似。
Length()返回数组的长度。GetAndIncrement(index)对数组中的元素进行自增。

5.原子字段更新器

AtomicReferenceFieldUpdater、AtomicIntegerFieldUpdater、AtomicLongFieldUpdater。利用字段更新器,可以针对对象的某个域(Field)进行原子操作,只能配合volatile修饰的字段使用,否则会出现异常。
AtomicReferenceFieldUpdater updater = new AtomicReferenceFieldUpdater(保护对象.class,应用对象.class,成员变量)。Updater.compareAndSet(对象,初始值,期望值)

6.原子累加器

比起原子整数的自增方法。LongAdder中的increment方法效率更高。性能提升的原因很简单,就是在有竞争时,设置多个累加单元,Therad-0累加Cell[0],而Thread-1累加Cell[1]… 最后将结果汇总。这样它们在累加时操作的不同的Cell变量,因此减少了CAS重试失败,从而提高性能。

7.unsafe

Unsafe对象提供了非常底层的,操作内存、线程的方法,Unsafe对象不能直接调用,只能通过反射获得。是原子类的底层实现。
Unsafe CAS操作:1.获取域的偏移地址。2.使用CAS方法替换成员变量的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值