ReentrantLock执行

ReentrantLock是基于AQS(AbstractQueuedSynchronizer)类实现的同步器框架,ReentrantLock是一个互斥锁,类似于Synchronized同步锁。其实是ReentrantLock一个内部类Sync继承AbstractQueuedSynchronizer类,Sync还定义了两个子类,实现公平锁(FairSync)和非公平锁(NonfairSync) ,用到的设计模式是模板设计模式。

ReentrantLock其实是基于自旋锁 、LockSupport、CAS原子操作、queue阻塞队列实现的。

ReentrantLock加锁方法是lock,释放锁的方法是unlock。

ReentrantLock lock=new ReentrantLock(true);传递一个参数,true表示公平锁,false表示非公平锁

lock.lock(); //加锁

lock.unlock();//释放锁

//重申:加解锁主要是维护一个state状态,被volatile修饰的 ,保证多线程及时可见性

volatile int state=0;//初始值是0,表示没有线程进行加锁,大于0表示有线程已经加锁了

阻塞队列节点Node的waitStatus状态:

       SIGNAL=-1   //表示可以可被唤醒

       CANCELLED=1   //表示出现异常,中断引起,需要废弃结束

       CONDITION = -2 // 条件等待
        PROPAGATE = -3 // 传播

        0 - 初始状态Init状态

lock加锁过程:

1、当调用lock方法(实际是sync.lock)的时候,当前线程t1调用tryRequire方法,先去获取的state的值,如果state=0, 判断当前双向链表的阻塞队列是否有存在节点,如果没有,线程t1调用compareAndSetState方法(使用cas操作)尝试修改state=1,如果修改成功setExclusiveOwnerThread,把自己线程设置为exclusiveOwnerThread变量中去,表示加锁成功;如果线程t1刚进来tryRequire方法发现state!=0,

那就去判断exclusiveOwnerThread是否等于当前线程t1,如果是state需要进行加1,这种就是重入锁,也表示加锁成功;反之,就是加锁失败了。

2、调用tryRequire尝试加锁失败,那么需要将线程t1写入到双线链表的阻塞队列,调用addWaiter创建一个Node对象节点,node对象中thread是t1,pre 和next其他属性还是NULL,addWaiter里面调用enq方法使用自旋方式for (;;)生成节点并写入队列,如果head节点和tail节点没有初始化也会创建一个空的节点;循环创建最终生成后是一个:head指向一个空节点node,t1的node的pre是空节点node,tail节点指向t1的node节点。

3、t1的node节点已经子队列中,接下来调用acquireQueued方法准备对其阻塞等待获取锁。也是通过for循环自旋方式去处理,阻塞之前还是会先判断t1的node节点pre节点是不是head头结点,如果是调用tryAcquire尝试去获取下锁(因为队列先进先出,按顺序获取锁,公平锁是这样),如果还是获取到了,会setHead方法,把当前线程t1的node的thread=null,pre=null,赋值给head;否则,调用shouldParkAfterFailedAcquire去修改waitStatus,判断prev=head节点的waitStatus是否是signal,是就返回,不是调用compareAndSetWaitStatus将head节点的waitStatus改成signal。

4、head节点的waitStatus改成signal后调用parkAndCheckInterrupt阻塞,实际是调用LockSupport.park(this)阻塞线程。lock加锁成功。

unlock解锁过程:

t1执行完后需要释放锁,调用unlock方法实际是调用sync.release方法,调用tryRelease方法尝试释放锁,(必须和加锁是一个线程,exclusiveOwnerThread会和当前线程作比较,不是抛异常),用当前state-1去处理,如果state=0,设置exclusiveOwnerThread=null,然后更新state值。tryRelease释放成功,compareAndSetWaitStatus操作把head节点的waitStatus改成0,获取到head的next节点t2,对节点t2进行释放锁LockSupport.unpark(thread)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值