1. 悲观锁
自我理解: 即认为所有的操作都可能修改数据,给所有的操作都上锁,这样会导致只有一个线程或进程能执行操作,效率低
日常悲观锁示例: 数据库的表锁,行锁,读写锁,sychronized 或者ReentrantLock 等独占锁就是悲观锁的体现
应用场景:读写操作比较多适合用悲观锁,防止脏数据
2. 乐观锁
自我理解:默认操作都不修改数据,只有当实际修改数据时才会去上锁
优点:多读操作时效率高
实现方式:
1. 数据库的版本号机制
在数据库新增version版本号字段,每次更新的时候version字段值+1;当提交更新时,只有当数据库version当前字段值等于读操作时获取到的version 值才允许更新
举例如下:
假设数据库中帐户信息表中有一个 version 字段,当前值为 1 ;而当前帐户余额字段( balance )为 $100 。
操作员 A 此时将其读出( version=1 ),并从其帐户余额中扣除 $50( $100-$50 )。
在操作员 A 操作的过程中,操作员B 也读入此用户信息( version=1 ),并从其帐户余额中扣除 $20 ( $100-$20 )。
操作员 A 完成了修改工作,将数据版本号加一( version=2 ),连同帐户扣除后余额( balance=$50 ),提交至数据库更新,此时由于提交数据版本大于数据库记录当前版本,数据被更新,数据库记录 version 更新为 2 。
操作员 B 完成了操作,也将版本号加一( version=2 )试图向数据库提交数据( balance=$80 ),但此时比对数据库记录版本时发现,操作员 B 提交的数据版本号为 2 ,数据库记录当前版本也为 2 ,不满足 “ 提交版本必须大于记录当前版本才能执行更新 “ 的乐观锁策略,因此,操作员 B 的提交被驳回。
这样,就避免了操作员 B 用基于 version=1 的旧数据修改的结果覆盖操作员A 的操作结果的可能。