heima并发23---并发工具包(2)---reentrantLock---238-244

锁就是改变state的状态,设置当前线程。不行的话就进入到等待队列(双向链表)里面去。

非公平锁的实现原理:

我们先找到ReentrantLock的构造器,默认是非公平锁。

非公平锁的加锁流程。

改变state的值。

原理图:

state head tail exclusiveOwnerThread都是Sync的属性。

state是1,则锁已经被占用了。进入下面的逻辑。

---238---

当出现竞争的时候则:

再尝试一次,这个方法没有讲解。

不成功进入acquireQueued方法,这个方法是尝试创建一个node对象,

addWaiter方法,加到等待队列里面,此时线程还是活着的。

再做最后的挣扎看看是不是能获得锁。node就是thread1的node。

这个代码的意思是:

在你尝试获取锁失败的时候是不是应该阻塞住呢?

第一次执行addWaiter,此时都是活着的,不是-1,没有后续节点的话waitStatus就是0。

进去:

进入tryAcquire,是当前的线程 就是重入锁就+1。

看下addWaiter方法,加锁失败进入队列。相当于EntryList,就是阻塞队列。

失败了进入enq方法排队。

指导成功为止。

---

创建节点之后,进入acquireQueue逻辑。

注意凡是带try的都是只改变状态的。

不是退不出循环而是失败后获得park阻塞。

这个重点。

acquireQueue是非常重要的语法。

死循环,先拿到当前的节点的前驱节点,看是不是头节点,是头结点还是有机会的。

失败。

等待队列是一个双向链表。

p是头节点,说明没有人和他竞争,就再获取一次。

失败了。首先应该park住。

看下几个变量的值:

waitStatus

shoudParkAfterFailedAcquired这个方法就是修改其前驱节点的waitStatus为-1。表示有责任唤醒其后继节点。每次添加都是把这个设置为-1。

第一次返回为false,因为只是将前驱的waitStatus变为-1。

第二次再进入for循环返回true。

再来:

此时假设Thread-0已经加锁了。

阻塞住了,但是不退出循环。

唤醒的话只有上一个节点是有资格唤醒的。

---239---

看下解锁。

进入:

看下tryRelease,只是不设置当前线程持有锁就抛出异常。

则进入unparkSuccessorl流程,唤醒一个阻塞队列的线程,进入这个方法:

唤醒的是离head最近的那个线程。

传进来的是头节点。

之前是一直在这里阻塞的,唤醒则在这里继续往下运行了,就是又进入了循环,是在哪里恢复的呢。

这次进去tryAcquire就成功了。

成功了设置为头节点,原来的就是头就断开了。

这个体现的:

---

这个是哪里的?

加锁的源码赏析:

---240---

此时别忘了我们是非公平的锁。

---241---

可重入的原理。

获取锁:

join wait sleep会抛出异常的。

解读这段代码:

正常获取。

重入就是增加计数器。

--------------------------------------------

释放锁。不是0每次-1,是0,释放唤醒。

---242---

可打断的原理。

关于park这个文章很好:https://www.cnblogs.com/septemberFrost/p/12200755.html

https://blog.csdn.net/fjse51/article/details/53928272

我们知道线程如果一直没办法获取锁的话就会进入acquireQueued方法不断的进行尝试的。

interrupt可以打断park,设置t_counter为1,此时有park就会消耗t_counter,否则返回。

设置中断标记为true就不会park。

_counter为1就不会park。

Thread.interrupted()会清除打断标记不会改变t_counter。

sleep检测到中断会清除打断标志不会改变t_counter。

如果一直尝试不到的话就进入parkAndcheckedInterrupt方法。

被打断了就返回真。

此时其他的线程找到这个线程可以打断也就是终止这个park,向下运行。

不清除打断标记park就会失效的。这个方法返回真。

这个就是清除打断标记下次再park时候还可以park住。

---

打断就是中止park的,现在中国特色线程正在阻塞这,其他的线程来打断了。

走到红箭头,此时会清除打断标记,如果其他线程来打断的话,还可以park住。返回值为真。

再往下进入,打断标记置为true。

但是只是置为true,还是会进入到进入循环,下次还是可以park住的。

------------------------------------------------------------------------------------------------------------------------------------

什么时候会用到呢?之后获得锁之久才会用到。

只有获得到锁才能获得锁作为返回标记返回。返回到哪里了呢?

这里打断标记为真就执行if块里面的内容。

返回到这里。

---

有什么不一样呢?

唤醒就抛出异常。

---243---

非公平锁。

公平锁:

体现公平。不成立才竞争的。

说明当前线程没有资格的。

代码赏析:

---244---

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值