java并发-ReentrantLock的lock和lockInterruptibly的区别
ReentrantLock的加锁方法Lock()提供了无条件地轮询获取锁的方式,lockInterruptibly()提供了可中断的锁获取方式。这两个方法的区别在哪里呢?通过分析源码可以知道lock方法默认处理了中断请求,一旦监测到中断状态,则中断当前线程;而lockInterruptibly()则直接抛出中断异常,由上层调用者区去处理中断。
lock获取锁过程中,忽略了中断,在成功获取锁之后,再根据中断标识处理中断,即selfInterrupt中断自己。 acquire操作源码如下:
/**
*默认处理中断方式是selfInterrupt
*/
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
acquireQueued,在for循环中无条件重试获取锁,直到成功获取锁,同时返回线程中断状态。该方法通过for循正常返回时,必定是成功获取到了锁。
/**
*无条件重试,直到成功返回,并且记录中断状态
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next =null; // help GC
failed =false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted =true;
}
}finally {
if (failed)
cancelAcquire(node);
}
}
可中断加锁,即在锁获取过程中不处理中断状态,而是直接抛出中断异常,由上层调用者处理中断。源码细微差别在于锁获取这部分代码,这个方法与acquireQueue差别在于方法的返回途径有两种,一种是for循环结束,正常获取到锁;另一种是线程被唤醒后检测到中断请求,则立即抛出中断异常,该操作导致方法结束。
/**
* Acquires in exclusive interruptible mode.
* @param arg the acquire argument
*/
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next =null; // help GC
failed =false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
}finally {
if (failed)
cancelAcquire(node);
}
}
结论:ReentrantLock的中断和非中断加锁模式的区别在于:线程尝试获取锁操作失败后,在等待过程中,如果该线程被其他线程中断了,它是如何响应中断请求的。lock方法会忽略中断请求,继续获取锁直到成功;而lockInterruptibly则直接抛出中断异常来立即响应中断,由上层调用者处理中断。
那么,为什么要分为这两种模式呢?这两种加锁方式分别适用于什么场合呢?根据它们的实现语义来理解,我认为lock()适用于锁获取操作不受中断影响的情况,此时可以忽略中断请求正常执行加锁操作,因为该操作仅仅记录了中断状态(通过Thread.currentThread().interrupt()操作,只是恢复了中断状态为true,并没有对中断进行响应)。如果要求被中断线程不能参与锁的竞争操作,则此时应该使用lockInterruptibly方法,一旦检测到中断请求,立即返回不再参与锁的竞争并且取消锁获取操作(即finally中的cancelAcquire操作)
java并发-ReentrantLock的lock和lockInterruptibly的区别的更多相关文章
- 【多线程】Java并发编程:Lock(转载)
原文链接:http://www.cnblogs.com/dolphin0520/p/3923167.html Java并发编程:Lock 在上一篇文章中我们讲到了如何使用关键字synchronized ...
- [转载] java并发编程:Lock(线程锁)
作者:海子 原文链接: http://www.cnblogs.com/dolphin0520/p/3923167.html 出处:http://www.cnblogs.com/dolphin0520/ ...
- Java并发编程:Lock(转)
本文转自:http://www.cnblogs.com/dolphin0520/p/3923167.html Java并发编程:Lock 在上一篇文章中我们讲到了如何使用关键字synchronized ...
- 5、Java并发编程:Lock
Java并发编程:Lock 在上一篇文章中我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.l ...
- java 并发——ReentrantLock
java 并发--ReentrantLock 简介 public class ReentrantLock implements Lock, java.io.Serializable { // 继承了 ...
- 【java并发编程】Lock & Condition 协调同步生产消费
一.协调生产/消费的需求 本文内容主要想向大家介绍一下Lock结合Condition的使用方法,为了更好的理解Lock锁与Condition锁信号,我们来手写一个ArrayBlockingQueue. ...
- Java并发编程之Lock
重入锁ReentrantLock 可以代替synchronized, 但synchronized更灵活. 但是, 必须必须必须要手动释放锁. try { lock.lock(); } finally ...
- Java 并发开发:Lock 框架详解
摘要: 我们已经知道,synchronized 是Java的关键字,是Java的内置特性,在JVM层面实现了对临界资源的同步互斥访问,但 synchronized 粒度有些大,在处理实际问题时存在诸多 ...
- 【转】Java并发编程:Lock
阅读目录 一.synchronized的缺陷 二.java.util.concurrent.locks包下常用的类 三.锁的相关概念介绍 来自: http://www.importnew.com/18 ...
随机推荐
- PCA: PCA的具体实现过程
数据预处理:mean normalization & feature scaling 先进行均值归一化(mean normalization),计算出每个特征的均值(uj),然后用xj-uj ...
- 阿里云——扩展Linux系统盘
前言 地址|https://help.aliyun.com/document_detail/111738.html?spm=a2c4g.11186623.2.7.1d284c07SFRBaq#sect ...
- websocket简单样例
服务端 var server = require('ws').Server; }); serv.on('connection',function(socket){ socket.send('hello ...
- *arg和**kwarg作用
*args:可以理解为只有一列的表格,长度不固定. **kwargs:可以理解为字典,长度也不固定. 1.函数调用里的*arg和**kwarg: (1) *arg:元组或列表 ...
- noip初赛试题
链接: https://pan.baidu.com/s/1yoOMIUqMRBnBUPprC3o6HQ&shfl=shareset 提取码: m8ns 复制这段内容后打开百度网盘手机App,操 ...
- Problem F. Wiki with String
Problem F. Wiki with StringInput file: standard input Time limit: 1 secondOutput file: standard outp ...
- LeetCode 685. Redundant Connection II
原题链接在这里:https://leetcode.com/problems/redundant-connection-ii/ 题目: In this problem, a rooted tree is ...
- (尚019)Vue基于脚手架编写项目
vue_demo目录结构截图: (1)图一 (2).图二 (3).图三 (四).图四 (5).图五 (6).图六 (7).图七 不能随便改入口文件的名字,因为已经配置好了 (8).图八 (9).图九 ...
- learning at command AT+CFUN
[Purpose] Learning how to controls the functionality level. It can also be used to reset the UE (飞行模 ...
- vigil deb 包制作
前边有写过简单rpm 包的制作,现在制作一个简单的deb 包. deb 包的制作是通过源码编译+ fpm 环境准备 rust curl https://sh.rustup.rs -sSf | sh 配 ...