ReentrantLock 是可重入的互斥锁,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

ReentrantLock 将由最近成功获得锁,并且还没有释放该锁的线程所拥有。当锁没有被另一个线程所拥有时,调用 lock 方法的线程将成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。

此类的构造方法接受一个可选的 fairness 参数。当设置为 true 时,在多个线程的争用下,这些锁倾向于将访问权授予等待时间最长的线程。否则此锁将无法保证任何特定访问顺序。与采用默认设置(使用不公平锁)相比,使用公平锁的程序在许多线程访问时表现为很低的总体吞吐量(即速度很慢,常常极其慢),但是在获得锁和保证锁分配的均衡性时差异较小。不过要注意的是,公平锁不能保证线程调度的公平性。因此,使用公平锁的众多线程中的一员可能获得多倍的成功机会,这种情况发生在其他活动线程没有被处理并且目前并未持有锁时。还要注意的是,未定时的 tryLock 方法并没有使用公平设置。因为即使其他线程正在等待,只要该锁是可用的,此方法就可以获得成功。

建议在调用 lock 方法后总是立即接着使用 try 块。典型的代码如下:

class X {
private final ReentrantLock lock = new ReentrantLock();
// ... public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}

除了实现 Lock 接口,此类还定义了 isLocked 和 getLockQueueLength 方法,以及一些相关的 protected 访问方法,这些方法对检测和监视可能很有用。

该类的序列化与内置锁的行为方式相同:一个反序列化的锁处于解除锁定状态,不管它被序列化时的状态是怎样的。

ReentrantLock 的方法

getHoldCount()

查询当前线程保持此锁的次数。

对于与解除锁操作不匹配的每个锁操作,线程都会保持一个锁。

保持计数信息通常只用于测试和调试。例如,如果不应该使用已经保持的锁进入代码的某一部分,则可以声明如下:

class X {
ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
assert lock.getHoldCount() == 0;
lock.lock();
try {
// ... method body
} finally {
lock.unlock();
}
}
}

isHeldByCurrentThread()

查询当前线程是否保持此锁。

与内置监视器锁的 Thread.holdsLock(java.lang.Object) 方法类似,此方法通常用于调试和测试。例如,只在保持某个锁时才应调用的方法可以声明如下:

class X {
ReentrantLock lock = new ReentrantLock();
// ... public void m() {
assert lock.isHeldByCurrentThread();
// ... method body
}
}

还可以用此方法来确保某个重入锁是否以非重入方式使用的,例如:

class X {
ReentrantLock lock = new ReentrantLock();
// ... public void m() {
assert !lock.isHeldByCurrentThread();
lock.lock();
try {
// ... method body
} finally {
lock.unlock();
}
}
}

isLocked()

查询此锁是否由任意线程保持。此方法用于监视系统状态,不用于同步控制。

isFair()

如果此锁的公平设置为 true,则返回 true。

getOwner()

返回目前拥有此锁的线程,如果此锁不被任何线程拥有,则返回 null。

hasQueuedThreads()

查询是否有些线程正在等待获取此锁。注意,因为随时可能发生取消,所以返回 true 并不保证有其他线程将获取此锁。此方法主要用于监视系统状态。

hasQueuedThread(Thread thread)

查询给定线程是否正在等待获取此锁。注意,因为随时可能发生取消,所以返回 true 并不保证此线程将获取此锁。此方法主要用于监视系统状态。

getQueueLength()

返回正等待获取此锁的线程估计数。该值仅是估计的数字,因为在此方法遍历内部数据结构的同时,线程的数目可能动态地变化。此方法用于监视系统状态,不用于同步控制。

getQueuedThreads()

返回一个 collection,它包含可能正等待获取此锁的线程。因为在构造此结果的同时实际的线程池可能动态地变化,所以返回的 collection 仅是尽力的估计值。所返回 collection 中的元素没有特定的顺序。

hasWaiters(Condition condition)

查询是否有些线程正在等待与此锁有关的给定条件。注意,因为随时可能发生超时和中断,所以返回 true 并不保证将来某个 signal 将唤醒线程。此方法主要用于监视系统状态。

getWaitQueueLength(Condition condition)

返回等待与此锁相关的给定条件的线程估计数。注意,因为随时可能发生超时和中断,所以只能将估计值作为实际等待线程数的上边界。此方法用于监视系统状态,不用于同步控制。

getWaitingThreads(Condition condition)

返回一个 collection,它包含可能正在等待与此锁相关给定条件的那些线程。因为在构造此结果的同时实际的线程池可能动态地变化,所以返回 collection 的元素只是尽力的估计值。所返回 collection 中的元素没有特定的顺序。

Java Concurrency - ReentrantLock的更多相关文章

  1. 《Java Concurrency》读书笔记,使用JDK并发包构建程序

    1. java.util.concurrent概述 JDK5.0以后的版本都引入了高级并发特性,大多数的特性在java.util.concurrent包中,是专门用于多线并发编程的,充分利用了现代多处 ...

  2. Java之ReentrantLock公平锁和非公平锁

    在Java的ReentrantLock构造函数中提供了两种锁:创建公平锁和非公平锁(默认).代码如下: public ReentrantLock() { sync = new NonfairSync( ...

  3. 深入浅出 Java Concurrency (35): 线程池 part 8 线程池的实现及原理 (3)[转]

    线程池任务执行结果 这一节来探讨下线程池中任务执行的结果以及如何阻塞线程.取消任务等等. 1 package info.imxylz.study.concurrency.future;2 3 publ ...

  4. 深入浅出 Java Concurrency (33): 线程池 part 6 线程池的实现及原理 (1)[转]

    线程池数据结构与线程构造方法 由于已经看到了ThreadPoolExecutor的源码,因此很容易就看到了ThreadPoolExecutor线程池的数据结构.图1描述了这种数据结构. 图1 Thre ...

  5. Java Concurrency in Practice 读书笔记 第十章

    粗略看完<Java Concurrency in Practice>这部书,确实是多线程/并发编程的一本好书.里面对各种并发的技术解释得比较透彻,虽然是面向Java的,但很多概念在其他语言 ...

  6. Java Concurrency - 浅析 CountDownLatch 的用法

    The Java concurrency API provides a class that allows one or more threads to wait until a set of ope ...

  7. Java Concurrency - 浅析 CyclicBarrier 的用法

    The Java concurrency API provides a synchronizing utility that allows the synchronization of two or ...

  8. Java Concurrency - 浅析 Phaser 的用法

    One of the most complex and powerful functionalities offered by the Java concurrency API is the abil ...

  9. Java Concurrency - 线程执行器

    Usually, when you develop a simple, concurrent-programming application in Java, you create some Runn ...

随机推荐

  1. [置顶] 文件和目录(一)--unix环境高级编程

    普通文件和目录linux中最多的两类文件,linux中一共有七种类型的文件,如下: 1.普通文件 2.目录 3.字符特殊设备 4.块特殊设备 5.FIFO,又叫命名管道 6.Socket,即套接字 7 ...

  2. 高扩展的基于NIO的服务器架构(二)

    接上文高扩展的基于NIO的服务器架构 Reactor模式 如下图所示,将不同事件的检测分离开,当一种事件发生时一个事件处理器EventHandler将通知与该事件处理相对应的专用工作线程 采用这种架构 ...

  3. 视频: 千重浪Linux系统调试技术培训 03-01_Basic-CPU-Register

    免费轻松学习Linux系统调试技术 欢迎收看本工作室放到优酷上播放的免费教学视频. 清晰! 完整!  无病毒! 请点击:http://v.youku.com/v_show/id_XNjM1OTQ3Mj ...

  4. nrpe 在ubuntu上安装遇到的问题

    Nagios Linux客户端需要安装NRPE进行数据收集,如果在Ubuntu系统下安装过程中遇到下面的错误提示:checking for SSL libraries... configure: er ...

  5. 搜狐cache文件夹设置

    比如说本来sohucache放在E盘,你想改到D盘.第一步:在运行中打开regedit,在弹出的HKEY_CURRENT_USER选中Software第二步:再选中SOHU再选中SoHuVA再选中Ca ...

  6. 数据返回[数据库基础]——图解JOIN

    废话就不多说了,开始... 一.提要 JOIN对于接触过数据库的人,这个词都不生疏,而且很多人很清楚各种JOIN,还有很多人对这个懂得也不是很透辟,此次就说说JOIN操纵. 图片是很容易被接受和懂得, ...

  7. cdoj 574 High-level ancients dfs序+线段树

    High-level ancients Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/s ...

  8. Codeforces Round #280 (Div. 2) E. Vanya and Field 数学

    E. Vanya and Field Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/492/pr ...

  9. 判断文件是否为UTF8编码

    utf8的规则比较简单: 对于UTF-8编码中的任意字节B,如果B的第一位为0,则B为ASCII码,并且B独立的表示一个字符; 如果B的第一位为1,第二位为0,则B为一个非ASCII字符(该字符由多个 ...

  10. [原创]经历:asp.net oracle 部署问题以及解决方法

    精简的美丽...... 一.环境    开发环境        win7 64bit         Vs2010        Oracle 11g r2 64bit        <inst ...