第七章 ReentrantLock总结
常用方式:
int a = 12;
//注意:通常情况下,这个会设置成一个类变量,比如说Segement中的段锁与copyOnWriteArrayList中的全局锁
final ReentrantLock lock = new ReentrantLock(); lock.lock();//获取锁
try {
a++;//业务逻辑
} catch (Exception e) {
}finally{
lock.unlock();//释放锁
}
1、非公平锁获取锁的步骤lock()
基于CAS尝试将state(锁数量)从0设置为1
A、如果设置成功,设置当前线程为独占锁的线程;
B、如果设置失败,还会再获取一次锁数量,
B1、如果锁数量为0,再基于CAS尝试将state(锁数量)从0设置为1一次,如果设置成功,设置当前线程为独占锁的线程;
B2、如果锁数量不为0或者上边的尝试又失败了,查看当前线程是不是已经是独占锁的线程了,如果是,则将当前的锁数量+1;
如果不是,则将该线程封装在一个Node内,并加入到等待队列中去,然后挂起park。等待被其前一个线程节点唤醒。
2、公平锁获取锁的步骤lock()
获取一次锁数量,
B1、如果锁数量为0,如果当前线程是等待队列中的头节点,基于CAS尝试将state(锁数量)从0设置为1一次,如果设置成功,设置当前线程为独占锁的线程;
B2、如果锁数量不为0或者当前线程不是等待队列中的头节点或者上边的尝试又失败了,查看当前线程是不是已经是独占锁的线程了,如果是,则将当前的锁数量+1;如果不是,则将该线程封装在一个Node内,并加入到等待队列中去,然后挂起park。等待被其前一个线程节点唤醒。
3、解锁的步骤
1)获取当前的锁数量,然后用这个锁数量减去解锁的数量(这里为1),最后得出结果c
2)判断当前线程是不是独占锁的线程,如果不是,抛出异常
3)如果c==0,说明锁被成功释放,将当前的独占线程置为null,锁数量置为0,返回true
4)如果c!=0,说明释放锁失败,锁数量置为c,返回false
5)如果锁被释放成功的话,唤醒距离头节点最近的一个非取消的节点
4、ReentrantLock的四种获取锁方法对比
/**
*获取一个锁
*三种情况:
*1、如果当下这个锁没有被任何线程(包括当前线程)持有,则立即获取锁,锁数量==1,之后再执行相应的业务逻辑
*2、如果当前线程正在持有这个锁,那么锁数量+1,之后再执行相应的业务逻辑
*3、如果当下锁被另一个线程所持有,则当前线程处于休眠状态,直到获得锁之后,当前线程被唤醒,锁数量==1,再执行相应的业务逻辑
* 简言之,获取锁,如果锁无法获取,当前线程被阻塞,直到锁可以获取并获取成功为止。
*/
public void lock() {
sync.lock();//调用NonfairSync(非公平锁)或FairSync(公平锁)的lock()方法
} /**
* lockInterruptibly():
* 1、 在当前线程没有被中断的情况下获取锁。
* 2、如果获取成功,方法结束。
* 3、如果锁无法获取,当前线程被阻塞,直到下面情况发生:
* 1)当前线程(被唤醒后)成功获取锁
* 2)当前线程被其他线程中断
*/
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
} /**
* 四点注意:
* 1、如果其他线程没有持有这个锁,立即返回true,设置锁的数量为1
* 2、如果当前线程已经持有这个锁了,那么锁数量+1,立即返回true
* 3、如果其他线程占有这个锁,该方法立即返回false
* 4、要注意:这个锁是非公平锁(即无法用于公平锁策略中)
*/
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
} /**
* 在指定时间内这个锁某个时刻没有被其他线程占有并且当前线程没有被中断,获得这个锁
*
* 1)如果没有其他线程占有这个锁,则获得这个锁,立即返回true,锁数量+1
* 2)如果当前线程已经持有这个锁了,那么锁数量+1,立即返回true
* 3)如果这个锁被其他线程持有,当前线程阻塞,直到下面三种情况发生:
* A、当前线程(被唤醒后)成功的获取锁
* B、其他线程中断了当前线程
* C、指定时间超时(如果时间<=0,根本就不会等待)
*
* 如果该锁被用于公平锁:如果有其他线程在等待,即使判断出没有其他线程占有这个锁,当前线程也不会获取这个锁
*/
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
第七章 ReentrantLock总结的更多相关文章
- 精通Web Analytics 2.0 (9) 第七章:失败更快:爆发测试与实验的能量
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第七章:失败更快:爆发测试与实验的能量 欢迎来到实验和测试这个棒极了的世界! 如果Web拥有一个超越所有其他渠道的巨大优势,它就 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (38) ------ 第七章 使用对象服务之动态创建连接字符串和从数据库读取模型
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第七章 使用对象服务 本章篇幅适中,对真实应用中的常见问题提供了切实可行的解决方案. ...
- 《Entity Framework 6 Recipes》中文翻译系列 (41) ------ 第七章 使用对象服务之标识关系中使用依赖实体与异步查询保存
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 7-7 标识关系中使用依赖实体 问题 你想在标识关系中插入,更新和删除一个依赖实体 ...
- Java语言程序设计(基础篇) 第七章 一维数组
第七章 一维数组 7.2 数组的基础知识 1.一旦数组被创建,它的大小是固定的.使用一个数组引用变量,通过下标来访问数组中的元素. 2.数组是用来存储数据的集合,但是,通常我们会发现把数组看作一个存储 ...
- objective-c第七章课后练习2
题:改变第七章例子中print方法,增加bool参数,判断如果是YES则对分数进行约简 @interface Fraction : NSObject { //int num,den; } @prope ...
- 读《编写可维护的JavaScript》第七章总结
第七章 事件处理 7.1 典型用法 作者首先给了个我们一个处理事件的方法.看起来也没啥俩样,不过后来给出的优化方法很值得学习: // 不好的写法 function handleClick(even ...
- 第七章 LED将为我们闪烁:控制发光二极管
第七章 LED将为我们闪烁:控制发光二极管 本章我们将会看到一个完整的linux驱动程序,通过linux驱动程序控制LED的四个小灯,通俗的说就是通过向linux驱动程序来控制LED小灯的开关.用到 ...
- Getting Started With Hazelcast 读书笔记(第七章)
第七章 部署策略 Hazelcast具有适应性,能根据不同的架构和应用进行特定的部署配置,每个应用可以根据具体情况选择最优的配置: 数据与应用紧密结合的模式(重点,of就是这种) 胖客户端模式(最好用 ...
- apue第七章学习总结
apue第七章学习总结 1.main函数 程序是如何执行有关的c程序的? C程序总是从main函数开始执行.main函数的原型是 int main(int argc,char *argv[]); 其中 ...
随机推荐
- curl: (60) SSL certificate problem: unable to get local issuer certificate 错误
今天同事做微信管理的项目,请求接口返回如下错误SSL certificate problem: unable to get local issuer certificate. 此问题的出现是由于没有配 ...
- 【笔记】C#往TextBox的方法AppendText加入的内容里插入换行符
C# TextBox换行[huan hang]时你往往会想到直接付给一个含有换行[huan hang]符"\n"的字符[zi fu]串[zi fu chuan]给Text属性[sh ...
- Linux动态共享库
Linux操作系统上面的动态共享库大致分为三类: 一.操作系统级别的共享库和基础的系统工具库 libc.so, libz.so, libpthread.so等等,这些系统库会被放在/lib和/us ...
- Linux安装和配置Vim7.4
一.简介 Vim是一个类似于Vi的文本编辑器,不过在Vi的基础上增加了很多新的特性,Vim普遍被推崇为类Vi编辑器中最好的一个,事实上真正的劲敌来自Emacs的不同变体.1999 年Emacs被选为L ...
- 201621123008 《Java程序设计》 第三周学习总结
1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词,如类.对象.封装等 关键词:类,构造函数,方法重载,方法覆盖,封装,继承,多态,类被加载的过程,static,abstract, ...
- ShowMsg函数
ShowMsg():显示提示信息,跳转到相应页面 例子: ShowMsg(,);
- arduino 与 android 通过TCP进行字节收发
arduino #include <avr/wdt.h> #include <SoftwareSerial.h> #define FPIN 13 SoftwareSerial ...
- ardunio 实现RS485通讯-下位机
#include <SoftwareSerial.h> SoftwareSerial mySerial(,); byte ZERO=0x00; byte Addr=0x03; byte S ...
- 使用async-http-client实现异步批量http请求
最近项目中需要在微服务中调用rest接口,而且需要调用得次数很多,所以同步得http客户端已经不满足要求,在网上查阅资料后发现了async-http-client这个包得性能不错,所以写了个demo测 ...
- vue实现消息的无缝滚动效果
export default { data() { return { animate:false, items:[ {name:"马云"}, {name:"雷军" ...