并发源码|AQS、ReentratLock原理
AQS原理
底层使用如下组件
private volatile int state;
//标识同步状态,第一次加锁时设置为1,若重入加锁,则state递增。释放锁时state递减,若state=0时将owner设置为null,并且使用LockSupport.unpark(s.thread);方法唤醒等待队列中的第一个线程
//其他线程来获取锁时,若失败,则加入等待队列(双向链表),并且使用LockSupport.park(this);休眠此线程
private transient Thread exclusiveOwnerThread;
//标识当前线程所有者
//一个双向链表作为一个队列来使用,存放等待队列(保存待加锁的线程)。
//非公平锁:新来一个线程直接判断能不能加锁,若能加锁则直接加锁,不能加锁才放入等待队列
//公平锁:等待队列中的线程依次加锁,体现的“公平”的特点
ReentratLock
多个线程争抢锁
尝试加锁,public boolean tryLock(long timeout, TimeUnit unit) 如果加锁不成功,则等待一段时间不成功则设置当前线程waitstate为SIGNAL状态,并持续重试,若最终超过了等待时间则从队列中移除
ReentrantReadWriteLock读写锁
使用state的高低16位(因为int是32位)来标识读锁(高16位)和写锁(低16位),非0表示已经加过锁了
读锁,可以同时被多个线程同时持有。读请求可以并发起来
写锁,则是互斥的
Condition
可重入锁可以创建Condition,主要有2个方法await与notify/notifyAll。 await等待唤醒,await与notify/notifyAll唤醒对应conditionawait的线程。
Condition.await()原理:将自己加入condition等待队列、释放锁、挂起自己
如果在加锁等待队列里有人阻塞,会有unpark的过程,唤醒加锁等待队列中的队头元素的那个过程
signal唤醒的过程,大概的意思,就是把condition等待队列中的元素,转化为一个加锁等待队列中的元素
- 原文作者:
- 原文链接:https://leyou240.github.io/post/juc04_reentrantlock%E4%B8%8Eaqs/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。