并发编程-concurrent指南-Lock-可重入锁(ReentrantLock)
可重入和不可重入的概念是这样的:当一个线程获得了当前实例的锁,并进入方法A,这个线程在没有释放这把锁的时候,能否再次进入方法A呢?
- 可重入锁:可以再次进入方法A,就是说在释放锁前此线程可以再次进入方法A(方法A递归)。
- 不可重入锁(自旋锁):不可以再次进入方法A,也就是说获得锁进入方法A是此线程在释放锁钱唯一的一次进入方法A。
,具体区别查看可重入锁和不可重入锁区别。
ReentrantLock,意思是“可重入锁”。ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法。下面通过一些实例看具体看一下如何使用ReentrantLock。
lock()的正确使用方法
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MainLock {
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
final MainLock mainLock = new MainLock(); new Thread(new Runnable() {
@Override
public void run() {
mainLock.insert(Thread.currentThread());
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
mainLock.insert(Thread.currentThread());
}
}).start();
} public void insert(Thread thread){
lock.lock();//获取锁
try{
System.out.println(thread.getName() + "获取锁");
for(int i=0;i<5;i++){
System.out.println("------------------------" + thread.getName() + ":"+i+"------------------------");
}
}finally {
System.out.println(thread.getName() + "释放锁");
lock.unlock();//释放锁
}
}
}
结果:
Thread-0获取锁
------------------------Thread-0:0------------------------
------------------------Thread-0:1------------------------
------------------------Thread-0:2------------------------
------------------------Thread-0:3------------------------
------------------------Thread-0:4------------------------
Thread-0释放锁
Thread-1获取锁
------------------------Thread-1:0------------------------
------------------------Thread-1:1------------------------
------------------------Thread-1:2------------------------
------------------------Thread-1:3------------------------
------------------------Thread-1:4------------------------
Thread-1释放锁
tryLock()的使用方法
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MainTryLock {
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
final MainTryLock mainTryLock = new MainTryLock(); new Thread(){
@Override
public void run() {
mainTryLock.insert(Thread.currentThread());
}
}.start(); new Thread(){
@Override
public void run() {
mainTryLock.insert(Thread.currentThread());
}
}.start();
} public void insert(Thread thread){
if(lock.tryLock()){
try{
System.out.println(thread.getName() + "获取锁");
for(int i=0;i<5;i++){
Thread.sleep(200);
}
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println(thread.getName() + "释放锁");
lock.unlock();//释放锁
}
}else{
System.out.println(thread.getName()+"未获取到锁");
}
}
}
结果:
Thread-0获取锁
Thread-1未获取到锁
Thread-0释放锁
lockInterruptibly()响应中断的使用方法:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MainLockInterruptibl {
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
MainLockInterruptibl test = new MainLockInterruptibl();
MyThread thread1 = new MyThread(test);
MyThread thread2 = new MyThread(test);
thread1.start();
thread2.start(); try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.interrupt();
} public void insert(Thread thread) throws InterruptedException{
lock.lockInterruptibly(); //注意,如果需要正确中断等待锁的线程,必须将获取锁放在外面,然后将InterruptedException抛出
try {
System.out.println(thread.getName()+"得到了锁");
long startTime = System.currentTimeMillis();
for( int i=0;i<5;i++) {
TimeUnit.SECONDS.sleep(2);
}
} catch (Exception e){
e.printStackTrace();
}finally {
System.out.println(Thread.currentThread().getName()+"执行finally");
lock.unlock();
System.out.println(thread.getName()+"释放了锁");
}
}
static class MyThread extends Thread {
private MainLockInterruptibl test = null;
public MyThread(MainLockInterruptibl test) {
this.test = test;
}
@Override
public void run() {
try {
test.insert(Thread.currentThread());
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(Thread.currentThread().getName()+"被中断");
}
}
}
}
结果:
Thread-0得到了锁
java.lang.InterruptedException
Thread-1被中断
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at com.concurrent.MainLockInterruptibl.insert(MainLockInterruptibl.java:25)
at com.concurrent.MainLockInterruptibl$MyThread.run(MainLockInterruptibl.java:48)
Thread-0执行finally
Thread-0释放了锁
源码地址:https://github.com/qjm201000/concurrent_reentrantLock.git
并发编程-concurrent指南-Lock-可重入锁(ReentrantLock)的更多相关文章
- 并发编程-concurrent指南-Lock
既然都可以通过synchronized来实现同步访问了,那么为什么还需要提供Lock?这个问题将在下面进行阐述.本文先从synchronized的缺陷讲起,然后再讲述java.util.concurr ...
- Java多线程——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
- Java多线程系列——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
- synchronized关键字,Lock接口以及可重入锁ReentrantLock
多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...
- Java并发(九):重入锁 ReentrantLock
先做总结: 1.为什么要用ReentrantLock? (1)ReentrantLock与synchronized具有相同的功能和内存语义: (2)synchronized是重量级锁,性能不好.Ree ...
- 轻松学习java可重入锁(ReentrantLock)的实现原理
转载自https://blog.csdn.net/yanyan19880509/article/details/52345422,(做了一些补充) 前言 相信学过java的人都知道 synchroni ...
- 轻松学习java可重入锁(ReentrantLock)的实现原理(转 图解)
前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...
- Java 重入锁 ReentrantLock 原理分析
1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...
- 17_重入锁ReentrantLock
[概述] 重入锁可以完全代替synchronized关键字. 与synchronized相比,重入锁ReentrantLock有着显示的操作过程,即开发人员必须手动指定何时加锁,何时释放锁,所以重入锁 ...
- 重入锁 ReentrantLock (转)(学习记录)
重入锁(ReentrantLock)是一种递归无阻塞的同步机制.以前一直认为它是synchronized的简单替代,而且实现机制也不相差太远.不过最近实践过程中发现它们之间还是有着天壤之别. 以下是官 ...
随机推荐
- ubuntu进不去桌面
今天折腾ubunu的时候,总是进不去桌面,开机直接进入啦终端模式.在google帮助终于解决. sudo apt install --reinstall gnome-shell ubuntu-desk ...
- js,css引用顺序设定
遇到的困难 在ASP .NET MVC里面,会使用_Layout.cshtml来绘制一些全局的公共页面,以及引用相关的css和js而在每个独立的页面中,也有自己独立的js一般来说,希望公共的js放在独 ...
- MVC EF Code First
1 在Models里面创建类,用[Key]特性指定主键: 2 在Model里面增加导航属性: 3 在web.config里面增加连接字符串 4 创建继承于DbContext的类 5 创建Control ...
- NOPI 基本读写
//获取cell的数据,并设置为对应的数据类型 public object GetCellValue(ICell cell) { object value = null; try { if (cell ...
- Win8Metro(C#)数字图像处理--2.25二值图像距离变换
原文:Win8Metro(C#)数字图像处理--2.25二值图像距离变换 [函数名称] 二值图像距离变换函数DistanceTransformProcess(WriteableBitmap sr ...
- Python中的参数传递问题
首先需要说明python中元组,列表,字典的区别. 列表: 什么是列表呢?我觉得列表就是我们日常生活中经常见到的清单. 例如:lst = ['arwen',123] 向list中添加项有两种方法:ap ...
- 程序员该如何过好他的整个职业生涯?(最重要的是你得一直往前走。拐点不是你的工资。想起很久前有个人说我“逻辑性”比较强)good
作者|池建强 编辑|小智 戳阅读原文,获得短信提醒,不错过下次InfoQ大咖说直播! 1 写在前面 加入极客邦的第一天就被拉到了「大咖说」的现场,这也是我始料未及的事情.从锤子科技正式离职之后,我 ...
- Delphi移动开发笔记(一)
Delphi从XE4版本就开始支持移动开发了,但是笔者最近才开始学习这块内容.因为笔者原来一直使用的是Delphi7,对于很多新语法没有了解过,所以把其中一些东西记录下来. 程序开发,调 ...
- 使用.NET进行高效率互联网敏捷开发的思考和探索【一、概述】
不知从什么时候开始,创业变得很廉价,谈什么都是互联网,动辄融资千万.这阵风好像也刮向了程序员中,有那么一大批开发者,数据结构不好好学习.数据库原理不扎实掌握,在github上发布几个项目,用nodej ...
- SharePoint js操作原生的New/Edit表单
列表的表单,有个类似的需求:在New需隐藏特定字段,Edit时显示. 默认是New/Edit表单的字段是一样,就算在Content type 是隐藏也是同时影响两个表单. 如何做到仅仅在New时隐 ...