乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

悲观锁总是假设最坏的情况每次去拿数据的时候都认为别人会修改所以每 

次在拿数据的时候都会上锁这样别人想拿这个数据就会阻塞直到它拿到锁 

统的关系型数据库里边就用到了很多这种锁机制比如行锁表锁等读锁 

锁等都是在做操作之前先上锁再比如 Java 里面的同步原语 synchronized  

键字的实现也是悲观锁

乐观锁顾名思义就是很乐观每次去拿数据的时候都认为别人不会修改 

以不会上锁但是在更新的时候会判断一下在此期间别人有没有去更新这个数据

可以使用版本号等机制乐观锁适用于多读的应用类型这样可以提高吞吐量

像数据库提供的类似于 write_condition 机制其实都是提供的乐观锁 Java

 java.util.concurrent.atomic 包下面的原子变量类就是使用了乐观锁的一种实 

现方式 CAS 实现的

乐观锁的实现方式

1、使用版本标识来确定读到的数据与提交时的数据是否一致提交后修改版本标 

不一致时可以采取丢弃和再次尝试的策略

2、java 中的 Compare and Swap  CAS ,当多个线程尝试使用 CAS 同时更新 

同一个变量时只有其中一个线程能更新变量的值而其它线程都失败失败的 

线程并不会被挂起而是被告知这次竞争中失败并可以再次尝试。 CAS 操作 

中包含三个操作数 —— 需要读写的内存位置(V)、进行比较的预期原值(A)

和拟写入的新值(B)。如果内存位置 V 的值与预期原值 A 相匹配那么处理器会自 

动将该位置值更新为新值 B。否则处理器不做任何操作

CAS 缺点

1、ABA 问题

比如说一个线程 one 从内存位置 V 中取出 A,这时候另一个线程 two 也从内存中 

取出 A,并且 two 进行了一些操作变成了 B,然后 two 又将 V 位置的数据变成 A,

这时候线程 one 进行 CAS 操作发现内存中仍然是 A,然后 one 操作成功尽管线 

 one  CAS 操作成功但可能存在潜藏的问题 Java1.5 开始 JDK  atomic

包里提供了一个类 AtomicStampedReference 来解决 ABA 问题

 180   485 2、循环时间长开销大

对于资源竞争严重线程冲突严重的情况,CAS 自旋的概率会比较大从而浪 

费更多的 CPU 资源效率低于 synchronized。

3、只能保证一个共享变量的原子操作

当对一个共享变量执行操作时我们可以使用循环 CAS 的方式来保证原子操作

但是对多个共享变量操作时循环 CAS 就无法保证操作的原子性这个时候就可 

以用锁

猜你喜欢

转载自www.cnblogs.com/programb/p/12771123.html