• 并发编程原理学习-reentrantlock源码分析


    ReentrantLock基本概念

    ​ ReentrantLock是一个可重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁,并且在获取锁时支持选择公平模式或者非公平模式。与Synchronized不同的是,它使用起来更加灵活,Synchronized加锁释放锁都是隐式的,这种方式简化了锁的管理,但是扩展性不如显示的锁获取和释放的可操作性。

    可重入

    所谓可重入指的是当一个持有锁的线程再次获取锁时不会被自己阻塞,执行线程在获取锁之后仍然能连续多次地获取到该锁。

    公平锁与非公平锁

    公平与非公平是针对锁的获取顺序而言的,如果一个锁是公平的,那么锁的获取顺序就需要符合请求的时间顺序,也就是先请求的线程先获得锁。

    ReentrantLock源码解析

    ReentrantLock实现了Lock接口,因此,先分析一下Lock接口。

    image-20220731202433863

    Lock接口提供了以上几个方法定义。

    public interface Lock {
      // 尝试获取锁,如果当前线程获取不到锁,则会进入休眠状态,直到获取到锁为止
       void lock();
      
      // 可中断地获取锁,该方法会响应中断,在锁的获取中可以中断当前线程,在获取锁的过程中可以中断当前线程
       void lockInterruptibly() throws InterruptedException;
      // 尝试非阻塞的获取锁,调用该方法后立刻返回,如果能够成功获取到锁则返回true,否则返回false
       boolean tryLock();
      /**
      在超时时间内获取锁,一下3中情况会返回:
      1、当前线程在超时时间内获得了锁
      2、当前线程在超时时间内被中断
      3、超时时间结束,返回false
      */
       boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
      // 释放锁
       void unlock();
       Condition newCondition();
      
     
    }
    

    ReeterentLock源码

    非公平模式
     // 非公平获取锁 
    final boolean nonfairTryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                // 当前线程持有锁的数量
                int c = getState();
               // 尝试获取锁, 获取成功则返回true
                if (c == 0) {
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                // 已经持有锁
                else if (current == getExclusiveOwnerThread()) {
                  // 增加持有锁的数量
                    int nextc = c + acquires;
                    if (nextc < 0) // overflow
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
    
    释放锁
           protected final boolean tryRelease(int releases) {
                // 减去释放锁的数量
                int c = getState() - releases;
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                boolean free = false;
                // 锁的数量为0,说明已经全部释放锁
                if (c == 0) {
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                setState(c);
                return free;
            }
    
    公平模式
            protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                //当前线程没有持有锁
                if (c == 0) {
                    // 当前线程前一个节点是否为首节点
                    if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {
                      // 获取锁成功
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
              // 当前线程已经持有锁
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
                    if (nextc < 0)
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
    
  • 相关阅读:
    DDD进阶_领域事件是什么?如何开展领域事件驱动开发工作?
    web安全最亲密的战友Burp Suite2--target模块体验
    力扣 215. 数组中的第K个最大元素
    springboot定时任务Scheduled使用和弊端分析
    Speedoffice(Excel)中如何添加页眉页脚
    servlet的生命周期
    搭建一个自定义的工作流管理平台(二)
    利用Font Awesome图标库为自己的网站页面添加矢量图标
    docker 安装 RabbitMq
    JavaWeb项目--JavaEE入门级项目实战(文末有C语言实现类似项目的对比)
  • 原文地址:https://www.cnblogs.com/crstly/p/16551038.html