theme: jzman
「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!」
深入分析JUC之Lock接口这篇文章整体认识Lock接口,今天我们分析并实践应用Lock接口的重要实现
ReetrantLock
和ReentrantReadWriteLock
。
一、ReetrantLock实现类图分析
ReetrantLock是一个独占锁、可重入锁。所谓独占锁是只有一个线程可以获取占有它。ReetrantLock锁包括fairReetrantLock和unfairReetrantLock。fairReetrantLock
是指不同线程获取锁的机制是公平的,unfairReetrantLock
是指不同线程获取线程是不公平的。公平或不公平体现在是否多个线程按照申请锁的顺序来获取锁,如果是就是公平的,否则就是不公平的。
如上图UML类图所示。
- ReentrantLock 实现了Lock接口。
- 在ReentrantLock 中有一个成员变量sync,sync的类型是Sync,Sync是一个抽象类,它集成自AQS(AbstractQueuedSynchronizer)。
- 在ReentrantLock 中有fair lock,即类FairSync ;还有unfair lock,即l类NonFairSync ,这两个类都是Sync的子类,这意味着ReentrantLock 具体使用的时候只能在公平锁和非公平锁中任选其一,默认情况是不公平锁。
二、ReentrantReadWriteLock实现类图分析
ReentrantLock是独占锁,ReentrantReadWriteLock并完全是独占锁,它的读锁是共享锁,写锁是独占锁。所以ReentrantReadWriteLock允许多个读线程同时访问,但凡有一个写线程,其它的读线程就会被阻塞。大多数情况下,读场景多于写场景,所以在读多于写的场景下,读写锁能带来更好的并发性和更多的吞吐量。
如上图UML类图所示。
- ReentrantReadWriteLock是ReadWriteLock的实现类
- ReentrantReadWriteLock包含了成员变量sync、readLock,writeLock,sync的类型为Sync,这点与ReentrantLock一样,是从AQS继承而来的抽象类。readLock的类型是ReadLock,writeLock的类型是WriteLock,ReadLock和WriteLock都实现了Lock接口。
三、例子
ReentrantLock
public class LockExample { private static final ReentrantLock FAIR_LOCK = new ReentrantLock(true); private static int i; public static void add(){ FAIR_LOCK.lock(); try { Thread.yield(); i++; } catch (Exception e){ throw new RuntimeException(e); }finally { FAIR_LOCK.unlock(); } } public static void unsafeAdd(){ i++; } }
ReentrantReadWriteLock
public class ReadWriteLockExample { static final Map<String,String> CACHE = new HashMap<>(); static final ReentrantReadWriteLock RRW_LOCK = new ReentrantReadWriteLock(); static final Lock R_LOCK = RRW_LOCK.readLock(); static final Lock W_LOCK = RRW_LOCK.writeLock(); public static String get(String key){ R_LOCK.lock(); try{ return CACHE.get(key); } finally { R_LOCK.unlock(); } } public static void put(String key,String value){ W_LOCK.lock(); try{ CACHE.put(key,value); }finally { W_LOCK.unlock(); } } }