前言
悲观锁与乐观锁 只是2种不同的概念. 在JDK内各有不同的实现.
解析
- 悲观锁
悲观锁. 即. 认为: 我们每次修改数据时, 都会有其他人来修改数据. 所以, 我们在进行更新数据时, 都会加锁进行控制.
即 执行类似如下流程.
1- 锁定
2- 修改数据
3- 解除锁定
Java 中并发包的锁主要有2种: synchronized关键字
与RentrantLock对象
. 其中之一写法:
public void update(OptimisticLockObject object, int value) throws InterruptedException {
synchronized (object){
object.updateValue(value);
}
}
- 乐观锁
即认为: 在修改数据时, 并无其他线程对相同数据进行修改. 但是乐观锁会在修改前记录下数据数值,修改时进行比对. 我们经常使用的CAS
和原子类(也是用的CAS
). 都是乐观锁的实现. (注: CAS 即 Compare And Swap. 比较并更新.)
乐观锁的执行流程为:
1- 获取数据Value 和Version
2- 检测Value和Version是否正确.
3- 匹配成功即更新;
4- 匹配不成功即失败.
JDK中乐观锁实现为原子类和CAS. 手写一个CAS的流程并不困难.
public void update(){
int value = getValue();
int version = getVersion();
// 更新
if(value==getValue() && version == getVersion()){
// update
}else{
// wrong & 重复更新
}
}
Codes
import java.util.Random;
/**
* 乐观锁 & 悲观锁.
*
* */
public class OptimisticPessimisticLock {
static class OptimisticLockObject{
int value;
int version;
public OptimisticLockObject() {
init();
}
public void init() {
value = 0;
version = 1;
}
public int getVersion() {
return this.version;
}
public boolean checkVersion(int version) {
return this.version==version;
}
public void updateValue(int value) {
this.value = value;
version++;
}
}
static class OptimisticThread extends Thread {
public OptimisticLockObject object;
public OptimisticThread(OptimisticLockObject object) {
this.object = object;
}
public void run() {
try {
update(object,new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void update(OptimisticLockObject object, int value) throws InterruptedException {
int lastVersion = object.version;
Thread.sleep(2);
System.out.println(this.currentThread().getName()+" value:"+object.value+" | "+" lastVersion:"+lastVersion);
if(object.checkVersion(lastVersion)) {
object.updateValue(value);
System.out.println(this.currentThread().getName()+" "+object.value+":"+object.version);
System.out.println("OptimisticLock OK .Update OK.");
}else {
System.out.println(this.currentThread().getName()+" "+object.value+":"+object.version);
System.out.println("OptimisticLock Wrong. Update Wrong. Version Changed.");
}
}
}
static class PessimisticThread extends Thread {
public OptimisticLockObject object;
public PessimisticThread(OptimisticLockObject object) {
this.object = object;
}
public void run() {
try {
update(object,new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void update(OptimisticLockObject object, int value) throws InterruptedException {
synchronized (object){
int lastVersion = object.version;
Thread.sleep(2);
System.out.println(this.currentThread().getName()+" value:"+object.value+" | "+" lastVersion:"+lastVersion);
if(object.checkVersion(lastVersion)) {
object.updateValue(value);
System.out.println(this.currentThread().getName()+" "+object.value+":"+object.version);
System.out.println("Pessimistic Lock OK .Update OK.");
}else {
System.out.println(this.currentThread().getName()+" "+object.value+":"+object.version);
System.out.println("Pessimistic Lock Wrong. Update Wrong. Version Changed.");
}
}
}
}
// 乐观锁 Case
public static void optimisticLockCase() {
OptimisticLockObject obj = new OptimisticLockObject();
Thread threadA = new OptimisticThread(obj);
Thread threadB = new OptimisticThread(obj);
threadA.start();
threadB.start();
}
// 悲观锁 Case
public static void pessimisticLockCase() {
OptimisticLockObject obj = new OptimisticLockObject();
Thread threadA = new PessimisticThread(obj);
Thread threadB = new PessimisticThread(obj);
threadA.start();
threadB.start();
}
public static void main(String[]args) throws InterruptedException {
// optimisticLockCase();
pessimisticLockCase();
// 放在前面2个线程没有执行完毕. 停顿10秒钟.
Thread.sleep(10* 1000);
}
}
Others
- 排它锁(独占锁) & 共享锁
- 读锁 / 写锁
上面2项说的是一个东西.
Reference
[1]. 什么是乐观锁,什么是悲观锁
[2]. 面试官:如何实现一个乐观锁(小白都能看得懂的代码)