| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> Java并发学习笔记:ReentrantLock -> 正文阅读 |
|
[Java知识库]Java并发学习笔记:ReentrantLock |
锁的获取主要是这两个函数,当然还有 lockInterruptibly( ) 和 tryLock(long timeout, TimeUnit unit) 这种响应中断和带时间限制的函数,不过和普通的lock( )和tryLock( )机理大致相同,就不介绍了。先以非公平锁的lock流程为例: // 位于Sync中 final void lock() { if (!initialTryLock()) acquire(1); } // 位于NonfairSync中 final boolean initialTryLock() { Thread current = Thread.currentThread(); if (compareAndSetState(0, 1)) { // first attempt is unguarded setExclusiveOwnerThread(current); return true; } else if (getExclusiveOwnerThread() == current) { int c = getState() + 1; if (c < 0) // overflow throw new Error(“Maximum lock count exceeded”); setState?; return true; } else return false; } // 位于AQS中 public final void acquire(int arg) { if (!tryAcquire(arg)) acquire(null, arg, false, false, false, 0L); } // 位于NonfairSync中的 protected final boolean tryAcquire(int acquires) { if (getState() == 0 && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } 复制代码 可见,一个完整的最长的调用关系为:sync.lock( )->sync.initialTryLock( )->acquire(1)->tryAcquire(1)->acquire(many args)。 详细流程为: 先调用initialTryLock( ),方法首先尝试用CAS方式将state从0设置为1(state是AQS类的一个变量,用来说明锁是否被获取,自然被Sync类继承了),成功了就将此锁的拥有线程设置为此线程;否则,查看此线程是否已经拥有此锁,若是,则设置state的重入次数,由此可见,ReentrantLock是可重入锁,一个线程可多次获取。否则,返回false。 接着调用AQS类的acquire( ),首先会调用tryAcquire( )函数,这个函数是由NonfairSync重写的。在这里会再检查一下此锁是否被释放,若是,直接获取它,否则,返回false。 如果以上尝试都返回false了,说明这个锁一时半会确实获取不到,就调用AQS类的带许多参数的acquire( )函数,这个函数的作用是把这个线程放入这个锁的阻塞队列里。是AQS的内容,这里就不介绍了。 上面介绍了非公平锁的获取锁的流程。公平锁和非公平锁各自实现了initiTryLock( )和tryAcquire( )方法。对于公平锁来说,相较于非公平锁,获取锁的其它代码全都一样,只是在设置一个线程获取锁时,会多一个 再看tryLock(): final boolean tryLock() { Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(current); return true; } } else if (getExclusiveOwnerThread() == current) { if (++c < 0) // overflow throw new Error(“Maximum lock count exceeded”); setState?; return true; } return false; } 复制代码 这个方法在Sync类里实现,所以不管是不是公平锁,可以获取就直接获取锁。代码
和initialTyeLock( )类似,就不解释了。同时也可以看出,tryLock( )并不会把线程加入到阻塞队列里,获取失败就直接返回false了。 锁的释放 位于Sync中 public void unlock() { sync.release(1); } // 位于AQS中 public final boolean release(int arg) { if (tryRelease(arg)) { signalNext(head); return true; } return false; } // 位于Sync中 protected final boolean tryRelease(int releases) { int c = getState() - releases; if (getExclusiveOwnerThread() != Thread.currentThread()) throw new IllegalMonitorStateException(); boolean free = (c == 0); if (free) setExclusiveOwnerThread(null); setState?; return free; } 复制代码 释放锁时,首先调用AQS中的release(1)函数,接着调用Sync重写的tryRelease( )函数,在这里将锁的重入数减一,如果state变为了0,说明此锁被释放了,进行释放锁的操作 值得一提的是,这里的tryRelease( )函数和上述的tryAcquire( )函数不一样,后者由公平锁和非公平锁各自实现,而tryRelease( )则在Sync类里实现,公平锁和非公平锁共用。这是因为释放锁不用考虑是否公平,直接释放了就可以了。 创建条件对象 ReentrantLock另一个常用方法就是创建条件对象,在源码里也很简单。 public Condition newCondition() { return sync.newCondition(); } // 位于AQS final ConditionObject newCondition() { return new ConditionObject(); } 复制代码 newCondition( )方法和ConditionObject的主要操作都定义在AQS类里,这里不做介绍了。 一个ReentrantLock对象对应的阻塞和条件队列示意图如上。相关的AQS操作之后有空我会写一下。 锁的状态state 在上面获取和释放锁的代码里,经常会出现getState( )这个方法的身影。这个方法实际上是返回了state变量。state是AQS类的一个变量,在ReentrantLock里,用来标识锁的重入次数以及是否被持有。下面是关于它的一些方法: private volatile int state; protected final int getState() { return state; } protected final void setState(int newState) { state = newState; } protected final boolean compareAndSetState(int expect, int update) { return U.compareAndSetInt(this, STATE, expect, update); } 复制代码 这些方法均位于AQS类里。首先,state是一个volatile类型的变量,保证每个线程读到的state值都是最近一个线程更新的值。get和set方法比较简单,不再解释。最后有一个compareAndSetState( )方法:顾名思义,用CAS方式更新state的值。这里使用Unsafe类(类似于一个指针,直接操作对应地址的数据)进行更新: private static final Unsafe U = Unsafe.getUnsafe(); // 获取属性偏移量 private static final long STATE = U.objectFieldOffset(AbstractQueuedSynchronizer.class, “state”); 复制代码 锁的持有线程 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 0:06:41- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |