2.27ReentrantLock

ReentrantLock底层原理:CAS+AQS

ReentrantLock的基本实现可以概括为:先通过CAS尝试获取锁。如果此时已经有线程占据了锁,那就加入队列并且被挂起。当锁被释放之后,排在队列队首的线程会被唤醒,然后CAS再次尝试获取锁(与公平还是非公平)

在尝试获取锁的时候,如果状态为0,则表明此时无人占有锁。此时尝试进行CAS获取锁,一旦成功,则成功占有锁。如果状态不为0,再判断是否是当前线程获取到锁 。如果是的话,将状态+1,因为此时就是当前线程,不用CAS

ReentrantLock可重入锁。
1.如何理解可重入呢?排队打水,以家庭为单位。打你可以打水的时候(你获得了线程),你家人再来就不用排队了。直接进入线程工作。当前持有该锁的线程能够多次获取该锁,无需等待(阻塞)
2.用的是AQS:基于FIFO等待队列实现的 一个用于实现同步器基础框架:基于volatile int state这样的一个属性配合Unsafe工具对其原子性的操作来实现对当前锁的状态进行修改,state=0,表示Lock不被任何线程所占有。 state+双向链表
3.每次可重入发生时,state都会加1,直到为0才释放
4.state的修改又用到了CAS技术,只保证操作原子性,不保证可见性。
5.AQS的等待队列:入队列,出队列,等待锁挂起进程,锁释放等待线程唤起(非公平这时可以趁虚而入)

具体性能:
1.中断响应:(可解决死锁)
synchronized 来说,如果一个线程在等待锁,那么结果只有两种情况,获得这把锁继续执行,或者线程就保持等待。而使用重入锁,提供了另一种可能,这就是线程可以被中断。也就是在等待锁的过程中,程序可以根据需要取消对锁的需求
(比如产生了死锁,但得益于锁中断,最终解决了这个死锁)
2.锁申请等待限时(也可以用于解决死锁):
如果给定一个等待时间,让线程自动放弃
3.支持公平锁和非公平锁

几个重要方法:
lock():获得锁,如果锁被占用,进入等待。
lockInterruptibly():获得锁,但优先响应中断。
tryLock():尝试获得锁,如果成功,立即放回 true,反之失败返回 false。该方法不会进行等待,立即返回。
tryLock(long time, TimeUnit unit):在给定的时间内尝试获得锁。
unLock():释放锁。

AQS双向链表如何理解?
head是头指针,指向队列的首元素;tail是尾指针,指向队列的尾元素
每一个结点都是一个线程,,,,双向连接的哦
1.同步队列是个先进先出(FIFO)队列,获取锁失败的线程将构造结点并加入队列的尾部,并阻塞自己。如何才能线程安全的实现入队是后面讲解的重点,毕竟我们在讲锁的实现,这部分代码肯定是不能用锁的。
你想想啊入队列改变好几个玩意指向,你得让他线程安全啊
全用的CAS方式改变的指针指向,下面就是一个头结点更新的源代码
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}

2.队列首结点可以用来表示当前正获取锁的线程。
3.当前线程释放锁后将尝试唤醒后续处结点 中处于阻塞状态的线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值