🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## ReentrantLock独享式重入锁 ### 使用 ~~~ ReentrantLock takeLock = new ReentrantLock(); // 获取锁 takeLock.lock(); try { // 业务逻辑 } finally { // 释放锁 takeLock.unlock(); } ~~~ ## ReentrantReadWriteLock 读写分离独享式重入锁 因此理想的实现是: 1. 当有写线程时,则写线程独占同步状态。 2. 当没有写线程时只有读线程时,则多个读线程可以共享同步状态。 ~~~ public class ReadWriteCache { private static Map<String, Object> data = new HashMap<>(); private static ReadWriteLock lock = new ReentrantReadWriteLock(false); private static Lock rlock = lock.readLock(); private static Lock wlock = lock.writeLock(); public static Object get(String key) { rlock.lock(); try { return data.get(key); } finally { rlock.unlock(); } } public static Object put(String key, Object value) { wlock.lock(); try { return data.put(key, value); } finally { wlock.unlock(); } } ~~~ ## Semaphore共享式不可重入锁 ~~~ // 创建一个计数阈值为5的信号量对象 // 只能5个线程同时访问 Semaphore semp = new Semaphore(5); try { // 申请许可 semp.acquire(); try { // 业务逻辑 } catch (Exception e) { } finally { // 释放许可 semp.release(); } } catch (InterruptedException e) { ~~~ ## CountDownLatch计数式独享锁 ## Condition等待通知 1. 每当一个线程调用Condition.await()方法,那么该线程会释放锁,构造成一个Node节点加入到等待队列的队尾。 2. 每当一个线程调用Condition.signal()方法,那么该线程会等待队列的队尾节点移到AQS中 ### Condition原理 Condition实现等待的时候内部也有一个等待队列,等待队列是一个隐式的单向队列,等待队列中的每一个节点也是一个AbstractQueuedSynchronizer.Node实例。 每个Condition对象中保存了firstWaiter和lastWaiter作为队列首节点和尾节点,每个节点使用Node.nextWaiter保存下一个节点的引用,因此等待队列是一个单向队列。 每当一个线程调用Condition.await()方法,那么该线程会释放锁,构造成一个Node节点加入到等待队列的队尾。 每当一个线程调用Condition.signal()方法,那么该线程会等待队列的队尾节点移到AQS中