Java基础 悲观锁&乐观锁

前言

悲观锁与乐观锁 只是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]. 面试官:如何实现一个乐观锁(小白都能看得懂的代码)

©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页