乐观锁和悲观锁
Posted cjhtxdy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了乐观锁和悲观锁相关的知识,希望对你有一定的参考价值。
什么是悲观锁?
悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。
像 Java 中synchronized
和ReentrantLock
等独占锁就是悲观锁思想的实现。
public void performSynchronisedTask() synchronized (this) // 需要同步的操作 private Lock lock = new ReentrantLock(); lock.lock(); try // 需要同步的操作 finally lock.unlock();
高并发的场景下,激烈的锁竞争会造成线程阻塞,大量阻塞线程会导致系统的上下文切换,增加系统的性能开销。并且,悲观锁还可能会存在死锁问题,影响代码的正常运行。
什么是乐观锁?
乐观锁总是假设最好的情况,认为共享资源每次被访问的时候不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源(也就是数据)是否被其它线程修改了(具体方法可以使用版本号机制或 CAS 算法)。
java.util.concurrent.atomic
包下面的原子变量类(比如AtomicInteger
、LongAdder
)就是使用了乐观锁的一种实现方式 CAS 实现的。 // LongAdder 在高并发场景下会比 AtomicInteger 和 AtomicLong 的性能更好 // 代价就是会消耗更多的内存空间(空间换时间) LongAdder sum = new LongAdder(); sum.increment();
LongAdder
),也是可以考虑使用乐观锁的,要视实际情况而定。java.util.concurrent.atomic
包下面的原子变量类)。
悲观锁和乐观锁
乐观锁和悲观锁:
参考博客:
http://blog.csdn.net/zhangwj0101/article/details/50946054
悲观锁:
PCC:Pessimistic Concurency Control,是一种并发控制的方法
悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度(悲观),因此,在整个数据处理过程中,将数据处于锁定状态。 悲观锁的实现,往往依靠数据库提供的锁机制 (也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)
悲观锁主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中
乐观锁:
OCC:Opitimistic Concurrency Control,是一种并发控制的方法
乐观锁相对悲观锁而言,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做
相对于悲观锁,在对数据库进行处理时,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本
实现数据版本:
数据版本:为数据增加一个版本标识,当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出的版本标识进行比对,如果数据库表当前版本号与第一次取出的版本标识值相等,则予以更新,否则认为是过期数据
实现数据版本有两种方式:使用版本号或者使用时间戳
以上是关于乐观锁和悲观锁的主要内容,如果未能解决你的问题,请参考以下文章