乐观锁与悲观锁区别

学习java过程中听到各种各样的锁,实在是眼花缭乱,只知其名不知其含义。其中大概分为乐观锁和悲观锁,数据库锁(排他锁、共享锁)还有很多并发中用的如自旋锁,阻塞锁、偏向锁等等。其中有的锁是一种思想而有的是具体实现,今天先了解一下最常听到的乐观锁和悲观锁是什么东西。

一、乐观锁

是应用系统层面和数据的业务逻辑层次上的(实际上并没有加锁,只是一种锁思想),利用程序处理并发, 它假定当某一个用户去读取某一个数据的时候,其他的用户不会来访问修改这个数据,但是在最后进行事务的提交的时候会进行数据的检查,以判断在该用户的操作过程中,没有其他用户修改了这个数据。乐观锁的实现大部分都是基于版本控制实现的, 除此之外,还有CAS操作实现

版本号方式:一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。

CAS操作方式:即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试。

二、悲观锁

顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

使用场景:乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

猜你喜欢

转载自blog.csdn.net/infperson/article/details/81607495