重入锁(1)

reentrantlock和synchornized
从前,sync加锁需要需要使用c/c++去调用本地的方法,使cpu在用户态和内核态之间转换,导致效率并不高。 jdk1.7时对其进行了优化,使其效率和reentrantlock差不多。

reentrantlock重入锁,有许多api可以调用,可直接在jdk层面解决同步问题。其分为公平锁和非公平锁,其内部有一个int类型的state用来记录是否有线程调用过.lock()方法,有一个等待队列来存储没抢到锁的线程。线程交替执行时,等待队列不被初始化,发生冲突时才会初始化该队列。

此队列是一个双向链表,队列被使用后,其头节点会一直是当前拿锁的线程的节点,由于是初始化队列,所以需要new一个thread为null的节点来代替获得锁的线程的节点作为头节点。

构造方法:

在这里插入图片描述
有两种构造方法,默认情况下会返回一个非公平锁,在有boolean类型参数时,true返回公平锁,false返回非公平锁。公平锁和非公平锁的区别在于是先调用CAS获取锁还是先调用acquire。

在这里插入图片描述
非公平锁:

会使用CAS直接尝试改变锁的状态,改变成功会返回true,这就导致如果上一个带锁线程改变状态的时间点和新来的线程尝试获取的时间刚好匹配,就会让新线程无视排队直接获取到锁。

公平锁:
在这里插入图片描述
acquire:
在这里插入图片描述
第一步尝试获取:
在这里插入图片描述

如果状态不为0,就判断请求线程是否是获取了锁的线程,true就计数+1,不是就跳出else if 返回 false
如果状态为0(自由)调用
在这里插入图片描述
查看当前的队列是否为空 与 当前头节点的next是否为空 或 头结点的next的thread是否是当前线程。(短路,s被赋值为h.next,若h.next != null ,才进行接下来的判断)

1.队列为空,返回false,可以获取锁。
2.头尾节点不同,队列不为空,头节点的下一个节点为空,表示上一个线程节点刚被弹出队列,当前线程即将成为队列里的第一个线程,返回true不可获取锁。
3.头尾节点不同,队列不为空,头的下一个节点不为空,当前请求线程不是头节点的下一个,返回true,表示没轮到这个线程拿锁,是下一个,返回false表示可以拿锁。

返回了false,则调用CAS拿锁并整个tryAcquire返回true,一路return到线程中继续执行。

返回了true,整个tryAcquire会返回false,并将当前线程加入队列。
//========================
加入队列代码如下:
在这里插入图片描述
在这里插入图片描述
总之,就是新建一个thread为null的节点,作为队列的头尾节点,并且一直保持thread==null的节点为头节点,有新线程进来时,将其尾插在当前tail节点后,并使其为尾节点。

//=======================
continue…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值