栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

RTL(ReentrantLock) 学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

RTL(ReentrantLock) 学习笔记

RTL(ReentrantLock) 可重入锁学习笔记
  • 什么是ReentrantLock 及其作用
    • 可重入性
    • 公平锁 & 非公平锁
    • Lock接口定义
    • RTL三个核心内部类Sync & NonfairSync & FairSync
      • Sync
      • NonfairSync
      • FairSync
      • RTL 的构造函数

什么是ReentrantLock 及其作用

ReentrantLock 基于 AQS(AbstractQueuedSynchronized),在并发编程中它可以实现公平锁和非公平锁来对资源进行同步,同时和synchronized一样,ReentrantLock支持可重入。ReentrantLock在调度上更灵活,支持更多丰富的功能。

可重入性

在并发编程中可重入性指的是 单个线程重新进入同一个子程序仍然是线程安全的 。一个线程可以不用释放而重复获取某个锁n次,只是在释放时需要相应释放n次。
死锁:若A线程既获取了锁,又在等待自己释放锁就会造成死锁。

公平锁 & 非公平锁
  • 非公平锁:不按照请求锁的顺序分配,不一定拥有获取锁的机会,但性能可能比公平锁高。
  • 公平锁:按照请求锁的顺序分配,拥有锁的机会稳定,但性能可能比非公平锁低。
Lock接口定义

RTL 实现了Lock接口,而Lock定义了6个方法,这6个方法定义了一些广泛的操作边界。

  • void Lock()方法:获取锁,加入当前锁被其他线程占用,则等待直到获取为止。
  • void lockInteruptibly() throws InterruptedException;方法:获取锁,假如当前线程在等待锁的过程中被中断,那么会退出等待,并抛出中断异常。
  • boolean tryLock(); 尝试获取锁,并立即返回,返回值代表的是是否成功获取到锁。
  • boolean tryLock(long time, TimeUnit unit) throws InterruptedException; 在一段时间内尝试获取锁,假如期间被中断,则抛出中断异常。
  • void unlock(); 释放锁。
  • Condition newCondition(); 新建一个绑定在当前Lock上的Condition对象。
    Conditon对象,表示一个等待状态, 获得锁的线程在某些时刻需要等待一些条件的完成才能继续执行,可以通过await()方法注册在Condition上进行等待,然后通过Condition方法的signal()方法将其唤醒。一个Lock对象可以关联多个Condition,多个线程可以被绑定到不同的Condition上,就可以分组唤醒。Condition还提供了和限时/中断相关的功能,丰富了线程的调度策略。
RTL三个核心内部类Sync & NonfairSync & FairSync Sync
abstract static class Sync extends AbstractQueuedSynchronizer {...}
  • RTL内部类Sync继承了AQS,说明AQS中所有预设的机制Sync都可以使用.
  • abstract 修饰Sync内部类,说明Sync需要通过其子类来进行实例化。NonfairSync和FairSync是Sync唯二的两个子类。
NonfairSync

非公平锁的具体实现

  • NonfairSync的具体实现中,Lock()方法内上来直接插队,先进行两次非公平的获取锁,若这两次获取锁失败,那么将进入FIFO队列进行排队直到获取锁。
  • 而tryAquire方法则是进行一次插队尝试获取锁,如果确实不想排队,那么上层可以写个循环不断调用这个方法尝试插队获取锁。
    
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
FairSync

公平锁的具体实现

  • lock()方法直接调用AQS的acquire()方法
  • tryAcquire()实现AQS接口,若当前线程已经获取锁,则对state值进行累加操作,可以继续使用锁,实现可重入。若锁一开始是空闲的,那么允许直接拿锁,若不空闲判断累加或者直接入队排号。
    
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        
        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;
        }
    }
RTL 的构造函数

ReentrantLock有两个构造函数

  • 默认无参构造函数使用了非公平锁的模式
  • 含参构造函数 可以自由选择使用公平锁还是非公平锁实现。
  • 一旦初始化就不能更改。因为RTL的属性Sync使用final修饰,一旦初始化就不可修改引用。
    
    private final Sync sync; // 私有变量使用final修饰
    
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/630976.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号