软件测试之python自动化测试5(web/app/接口自动化/自动化框架)57期
了解ReentrantLock获取和释放锁的过程。获取锁定进程整个过程可以总结为做两件事。成功获取锁,在当前线程中执行其他事情;锁获取失败,当前线程加入同步队列,同时阻塞当前线程。当第一个线)进来时,通过CAS将state属性更改为1。如果成功,通过setExclusiveOwnerThread()方法将exclusiveOwnerThread设置为当前线程。此时,当第二个线)进来并通过CAS将state属性更改为1时,它将失败。这时,它进入acquire()方法。最终会得出以下方米乐M6 M6米乐法:首先通过tryAcquire()方法再次尝试获取锁。tryAcquire()方法仍然通过CAS获得锁。此时,锁资源仍由第二个线程持有,因此它将返回false。现在看看acquire()方法中的if判断。此时,获取排队(添加服务员(节点。exclusiv米乐M6 M6米乐e)、arg)进行判断。这里需要执行两个方法addWaiter()和acquireQueued()。首先看addWaiter()方法。这种方法,我们需要注意以下四点。
首先会构造一个node节点(节点内部细节见其构造方法)。如果tail(同步队列尾节点指针)不为空,即同步队列不为空,那么步骤1中构造的节点将通过尾插入添加到队列中,然后返回。如果同步队列为空,那么执行enq()方法,它为我们做了两件事。如果同步队列为空,则初始化队列。初始化队列后,将节点node入队。通过addWaiter()方法和enq()方法,我们还可以看到,AQS中的同步队列是通过一个双向链表来实现的。当一个节点入队和出队时,需要修改两个指针(prev和next)。addWaiter()方法执行后,我们通过下图大致看一下此时同步队列中指向的节点。在这里,如果不太理解,可以回头看看enq()方法的执行流程。执行addWaiter()方法后,它将在入队后返回到新节点。然后开始执行acquireQueued()方法。这个方法做了五件事。获取当前节点的前任节点p。如果P是头节点,再尝试获取锁,如果成功获取锁,就可以跳出循环了。无法获米乐M6 M6米乐取锁。由shouldParkAfterFailedAcquire()将waitSatus改为-1(为什么改为-1?原因可以在AQS的源代码中找到,后续获取锁的过程会遵循这个逻辑)
4.ParkandChekingInterrupt()方法会阻塞当前线程,同时可以返回当前线程的中断状态errupted()会清除中断标志位)。经过上面的操作,我们可以知道线没有获得锁,被添加到同步队列中,并阻塞了它。总结起来就是四个字:“入队”“封”。此时,我们的同步队列也变成如下所示。执行后与上述addWaiter()方法相比,只是thread 1节点的前任节点,waitStaus设置为-1。释放锁定过程整个过程(仅考虑解锁成功)可以总结为三件事。释放锁资源;唤醒同步队列中头节点之后的节点对应的线被唤醒的线程试图竞争锁。如果竞争成功,则更新同步队列(即头节点出列)。当第一个线)执行自己的业务流程时,它将释放锁。至此,我们来看一下解除锁的过程。调用unlock()方法可以释放锁。需要注意的是,为了避免死锁,这个方法的调用需要放在最后的代码块中。当thread0释放锁时,它调用release()方法,该方法主要做两件事。调用tryRelease()方法来释放锁。在方法内部,状态被设置为0,exclusiveOwnerThread被setExclusiveOwnerThread()方法设置为null时,意味着此时锁资源被释放,没有线程持有锁资源。如果第一步返回true,即锁被成功释放,那么开始第二步。第二步是首先获取同步队列的头节点,并检查其waitStatus属性。这里,让我们把刚刚获得锁的节点的情况放在同步队列中。此时,我们的head节点的waitStatus为-1,所以我们将进入unparksuccess()方法。parksuccess()方法主要做以下三件事。注意第三步。根据我们当前的同步队列,LockSupport.unpark()方法将唤醒线。当执行unparksuccess()方法中的LockSupport.unpark()方法时,线)将被唤醒。线被唤醒后,我们来看看线的执行情况。此时,线将继续执行acquireQueued()方法中的for循环(注意:这是一个无限循环)。执行顺序与锁获取相同,但当与锁获取不同时,步骤2中的锁获取将会成功(因为thread0已经释放了锁)。成功获取锁后,当前同步队列中的头节点将出队。此时,同步队列中节点的情况如下。至此,释放锁的逻辑完成。其实总结起来很简单。首先释放锁资源,然后唤醒同步队列中头节点的下一个节点对应的线程,最后更新同步队列(出列)。摘要以上是ReentrantLock获取和释放锁的一般过程。通过本文,读者对ReentrantLock的锁的获取和释放过程有了一个大致的了解。细心的读者可能会发现,在获取锁时,acquireQueued()方法中有一个cancelAcquire()方法的调用逻辑。
电话:13644723777
传 真:+86-173-4169
手 机:13644723777
邮 箱:mile@nmgdp.net
地 址:内蒙古包头市昆区昆工路光彩商业街99号