【Java并发】重入锁ReentrankLock解析

转载请注明出处https://blog.csdn.net/Fury97/article/details/81367900

 

目录

重入锁

为什么需要重入锁

重入锁有哪些

ReentrankLock如何实现重入

公平锁与不公平锁

ReentrankLock中公平锁的实现方法

公平锁和非公平锁的优缺点

重入锁

顾名思义,就是可以支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁。

 

为什么需要重入锁

使用重入锁,可以在当一个线程获取对象A的锁之后,这个线程可以再次获取对象A上的锁。

假设某一同步方法是递归方法,那么就会不停的对此对象加锁,如果不使用重入锁,会导致线程1本身获取了对象A的锁,再获取锁时被阻塞住。

 

重入锁有哪些

我们常见的synchronized就是重入锁,而第二个重入锁ReentrankLock就是我们今天的主题。

 

ReentrankLock如何实现重入

首先明确概念:重入是指任意线程在获取到锁之后能够再次获取该锁而不会被阻塞。

实现该特性需要解决两个问题:

  1. 锁需要去识别获取锁的线程是否为当前占据锁的线程,如果是,则成功获取。
  2. 线程重复n次获取了锁,那么就要释放n次锁,否则其他线程还是无法获取该锁。ReentrankLock通过要求每次获取锁时进行计数自增,当锁被释放时,计数自减,计数为0时表示锁成功释放。所以前(n-1)次tryRelease()方法都是返回false,只有最后一次才返回true。

 

公平锁与不公平锁

公平锁:对于每一个线程来说,获取锁的顺序取决于线程提交请求的先后顺序。也就是FIFO,排队领锁,先来先得。

不公平锁:随缘。

我们常见的synchronized是不公平锁,所以使用synchronized有可能会出现某线程永远得不到锁而一直被阻塞。

ReentrankLock给我们提供了一个构造函数,我们可以通过构造函数来控制锁是否是公平的。

 

ReentrankLock中公平锁的实现方法

在同步队列中添加对“当前节点是否有前驱节点的判断”。

同步队列是一个队列,每一个获取锁失败的线程会成为队列中的一个节点,当持有锁的线程释放锁时会发出信号,让后面的节点的线程申请锁。

所以当前节点如果有前驱节点,即说明有比它来的更早的线程在前面,因此需要等待前驱节点中的线程获取并释放锁后,才能继续申请锁。

 

公平锁和非公平锁的优缺点

  • 公平锁没有非公平锁效率高,因为在非公平锁中经常会出现刚释放锁的线程再次获取了锁,而公平锁中线程需要不停切换。
  • 公平锁可以减少“饥饿”发生的概率,因为它总是保证来的最早的线程获得锁,而非公平锁不能保证。

 

参考资料:《Java并发编程的艺术》

    原文作者:java锁
    原文地址: https://blog.csdn.net/fury97/article/details/81367900
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞