JUC并发编程(8)——无锁、乐观锁和CAS

一、介绍

1.乐观锁 和 悲观锁

乐观锁和悲观锁是广义上的概念,根据是否锁住同步数据来判断。
悲观锁对同一个数据的并发操作,认为自己在使用数据的时候一定有别的线程来修改数据,因此每次操作同步数据时都会先加锁。在java中synchronized关键字和Lock的实现类都是悲观锁。
乐观锁认为自己再使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有更新,当前线程就能更新成功,反之则不行。在java中通过无锁编程来实现。

2.无锁

乐观锁是一个广泛的概念,而无锁便是乐观锁在java中的具体实现。
无锁不对资源进行锁定,所有线程都能访问并修改同一个资源,但是同时只有一个线程能修改成功。
无锁采用的是CAS(Compare And Swap 比较并交换),并不断循环尝试。

3.CAS

CAS涉及到三个操作数:
① 需要读写的内存值V
② 进行比较的值A
③ 需要写入的新值B
通过处理器的原子指令(cmpxchg)可以实现比较V=A并且B更新V。
在java.util.concurrent包中的各种原子类就是通过CAS来实现乐观锁的。
CAS虽然高效但是它存在三大问题:
① ABA问题
② 循环时间开销大,如果竞争激烈重试频繁发生,反而效率会受到影响
③ 只能保证一个共享变量的原子操作

二、Atomic

1.介绍

从jdk1.5以来,JDK并发包中提供了一些类来支持原子操作,它们属于乐观锁,通过cas实现。

2.原子整数

① AtomicInterger
② AtomicLong
③ AtomicBoolean

底层是调用unsafe类的cas api

AtomicInterger i = new AtomicInterger(0);
i.compareAndSet()

i.incrementAndGet(); //  ++i
i.getAndIncrement(); //  i++

i.getAndAdd(x); //  x++
i.addAndGet(x); //  ++X

i.updateAndGet(x -> x*10);

i.get() // 获取值

2.原子引用

① AtomicReference
② AtomicMarkableReference
③ AtomicStampedReference
需要注意的是AtomicReference比较的引用地址是否发生改变。这点用voliate修饰引用类型一样,这能保证引用类型地址发生改变时的可见性,不能保证引用类型属性发生改变的可见性。

AtomicReference<T> test = new AtomicReference<>(T t);

T t1 = test.get();
test .compareAndSet() // 返回值Boolean类型

之前提过CAS存在ABA问题,解决ABA的方法就是加个版本号。
而AtomicStampedReference就可以携带版本号

AtomicStampedReference<T t> test = AtomicStampedReference<>(T t,0) // 0就是版本号
T t1 = test.getReference(); // 获得原引用
int stamp = test.getStamp();  // 获得版本号
test.compareAndSet(t1,T newt,stamp,stamp + 1);

3.原子数组

① AtomicIntegerArray
② AtomicLongArray
③ AtomicReferenceArray

AtomicIntergerArray test = new AtomicIntergerArray(10); // 等同于创建一个长度为10的数组
test.getAndIncrement(index) // 数组对应下标值加1

4.字段更新器

① AtomicReferenceFieldUpdater
② AtomicIntegerFieldUpdater
③ AtomicLongFieldUpdater

AtomicReferenceFieldUpdater test = AtomicReferenceFieldUpdater.newUpdater(Student.class,T.class,"字段名称");
test .compareAndSet(T t,字段原值,字段新值);

5.原子累加器

jdk1.8出现了几个专门用来做累加的类,这些类比atomic类做累加效率要高。

new LongAdder();
adder.increment();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值