1. 前言
Java锁的种类 java中的锁种类是真的多。而locks包下也有一些。包结构如下:
- AbstractOwnableSynchronizer 一个线程拥有的同步器,这个类提供了创建锁和相关同步器的基础
- AbstractQueuedLongSynchronizer 所有的同步状态都是用long变量来维护的,而不是int,在需要64位的属性来表示状态的时候会很有用
- AbstractQueuedSynchronizer 为实现依赖于先进先出队列的阻塞锁和相关同步器(信号量、事件等等)提供的一个框架,它依靠int值来表示状态
- Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用。这个是被绑定在Lock上一起使用的。
- Lock 实现了比synchronized更多的功能,需要注意的是,为了确保可以释放锁,需要在finally语句块中unlock。
- LockSupport LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark()不会遇到“Thread.suspend 和 Thread.resume所可能引发的死锁”问题。
- ReadWriteLock 读写锁,读和写是互斥的,多个读锁不互斥,也就是说,在读的时候,不能写,在写的时候,不能读,但是在读的时候可以有多个线程同时读。
- ReentrantLock 可重入锁
- ReentrantReadWriteLock 可重入读写锁
- StampedLock Java 1.8提供了一种读写锁,
2. Condition
Condition是和Lock绑定使用的。Lock#newCondition方法返回一个Condition。
使用方法如下:
- 创建Lock
- Lock#newCondition 返回新的Condition (可以多次调用)
- Condition#await 会导致线程挂起直到signalled,或者中断。
- Condition#signal 唤醒线程
ArrayBlockingQueue中有大量这样的用法。如图:
3. LockSupport
- park方法能将阻塞线程或者
- unpark 方法唤醒线程
4. ReentrantReadWriteLock
ReentrantReadWriteLock是locks包中提供的读写锁的一种实现,用法也很简单。一般用jdk提供的ReentrantReadWriteLock。
用法如下
- 初始化
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Lock readLock = readWriteLock.readLock();
Lock writeLock = readWriteLock.writeLock();
- 在需要读的时候
readLock.lock()
,用完之后readLock.unlock()
- 在需要写的时候
writeLock.lock()
,用完之后writeLock.unlock()
ReentrantReadWriteLock支持锁降级
什么是锁降级呢。从读写角度来看,写的级别是高于读的。咱们看例子
public static void main(String[] args){
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
final Lock readLock = readWriteLock.readLock();
final Lock writeLock = readWriteLock.writeLock();
// 读
readLock.lock();
System.err.println("我是读锁");
// 写
writeLock.lock();
System.err.println("我是写锁");
}
很明显,由于不支持锁升级,因此,会阻塞。输出结果如下
我们上面读写翻个顺序。
// 写
writeLock.lock();
System.err.println("我是写锁");
// 读
readLock.lock();
System.err.println("我是读锁");
输出结果如下:
锁降级,将写入锁降级为读锁(很好理解,就像写权限要高于读权限一样)
5. ReentrantLock
也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响
这种锁在ArrayBlockingQueue中有用到。
关于用法这里就不说了。
ReentrantLock可是实现公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
从构造函数中来看,是支持公平锁的。
公平锁,等待时间长的优先获得锁。
6. StampedLock
这里想的半天,还是觉得参考资料里面写的很完美,所以,我就不献丑了。大家去看看吧。
参考资料