公平锁和非公平锁的区别
- 公平锁 指在分配锁前检查是否有线程在排队等待获取该锁,优先将锁分配给排队时间最长的线程
-
非公平锁 指在分配锁时不考虑线程排队等待的情况,直接尝试获取锁,在获取不到锁时再排到队尾等待
因为公平锁需要在多核的情况下维护一个锁线程等待队列,基于该队列进行锁的分配,因此效率比非公平锁低很多,java中的synchronized时非公平锁,ReentranLock默认的lock方法采用的时非公平锁。
读写锁:ReadWriteLock
- 在Java中通过Lock接口及对象可以方便的为对象加锁和释放锁,但是这种锁不区分读写,叫做普通锁。为了提供性能,Java提供了读写锁,读写锁分为读锁和写锁,在写的地方使用写锁,在没有写的地方,读时无阻塞的。
- 如果系统要求共享数据可以同事支持很多线程并发读,但不能支持很多线程并发写,那么使用读锁能很大程度地提高效率,如果系统要求共享数据在同一时刻只能有一个线程在写,再写的过程中不能读取共享数据,则需要使用写锁。
public class SeafCache{
private final Map<String,Object> cache= new HashMap<String,Object>();
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock =rwlock.readLock();//step1:定义读锁
private final Lock writeLock =rwlock.writeLock();//step2:定义写锁
public Object get(String key){
readLock.lock();
try{
return cache.get(key);
}finally{
readLock.unLock();
}
}
//step4:再写数据时加写锁
public Object put(String key,Object value){
writeLock.lock();
try{
return cache.put(key,value);
}finally{
writeLock.lock();
}
}
}
共享锁和独占锁
- 独占锁:也叫互斥锁,每次只允许一个线程持有该锁,ReentrantLock为独占锁的实现
-
共享锁:允许多个线程同时获取该锁,并发访问共享资源。ReentrantReadWriteLock中的读锁为共享锁的实现。
ReentrantReadWriteLock的加锁和解锁操作最终都调用内部类Sync提供的方法。Sync对象通过继承AQS(Abstract Queued Synchronizer)进行实现。AQS的内部类Node定义了两个常量SHARED和EXCLUSIVE,费别标识AQS队列中等待线程的锁获取模式。
独占锁是一种悲观的枷锁策略,同一时刻只允许一个读线程读取锁资源,限制了读操作的并发性;因为并发读线程并不会影像数据的一致性,因此共享锁采用了乐观的枷锁策略,允许多个执行读操作的线程同时访问共享资源。
版权声明:本文为yitian881112原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。