乐观锁和悲观锁
定义
什么是悲观锁?
悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞,直到锁被上一个持有者释放。也就是说,共享资源每次只给一个线程使用,其他线程阻塞,用完后再把资源转让给其他线程。
Java 中 synchronized 和 ReentrantLock 等独占锁就是悲观锁思想的实现。
public void performSynchronisedTask() {synchronized (this) {// 需要同步的操作}
}private Lock lock = new ReentrantLock();
lock.lock();
try {// 需要同步的操作
} finally {lock.unlock();
}
在高并发场景下,激烈的锁竞争会造成线程阻塞,大量阻塞线程会导致系统的上下文切换,增加系统的性能开销。并且,悲观锁还可能会存在死锁的问题,影响代码正常运行。
什么是乐观锁?
乐观锁总是假设最好的情况,认为共享资源每次被访问时不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源是否被其他线程修改。
在高并发的场景下,乐观锁相比悲观锁,不存在锁竞争造成线程阻塞,也不会有死锁的问题,在性能上往往会更胜一筹。但是,如果冲突频繁发生(写占比多的情况),会频繁的失败和重试,这样同样会影响性能,导致 CPU 飙升。