可重入和不可重入的概念是这样的:当一个线程获得了当前实例的锁,并进入方法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)的更多相关文章

  1. 并发编程-concurrent指南-Lock

    既然都可以通过synchronized来实现同步访问了,那么为什么还需要提供Lock?这个问题将在下面进行阐述.本文先从synchronized的缺陷讲起,然后再讲述java.util.concurr ...

  2. Java多线程——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  3. Java多线程系列——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  4. synchronized关键字,Lock接口以及可重入锁ReentrantLock

    多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...

  5. Java并发(九):重入锁 ReentrantLock

    先做总结: 1.为什么要用ReentrantLock? (1)ReentrantLock与synchronized具有相同的功能和内存语义: (2)synchronized是重量级锁,性能不好.Ree ...

  6. 轻松学习java可重入锁(ReentrantLock)的实现原理

    转载自https://blog.csdn.net/yanyan19880509/article/details/52345422,(做了一些补充) 前言 相信学过java的人都知道 synchroni ...

  7. 轻松学习java可重入锁(ReentrantLock)的实现原理(转 图解)

    前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...

  8. Java 重入锁 ReentrantLock 原理分析

    1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...

  9. 17_重入锁ReentrantLock

    [概述] 重入锁可以完全代替synchronized关键字. 与synchronized相比,重入锁ReentrantLock有着显示的操作过程,即开发人员必须手动指定何时加锁,何时释放锁,所以重入锁 ...

  10. 重入锁 ReentrantLock (转)(学习记录)

    重入锁(ReentrantLock)是一种递归无阻塞的同步机制.以前一直认为它是synchronized的简单替代,而且实现机制也不相差太远.不过最近实践过程中发现它们之间还是有着天壤之别. 以下是官 ...

随机推荐

  1. 各linux版本重启apache命令

    各linux版本重启apache命令 Slackware Linux命令: /etc/rc.d/rc.httpd restart ubuntu.Debian 系统命令: /etc/init.d/apa ...

  2. 模拟请求(模拟header gzip解压 泛型)

    WebClient HeaderData是自定义类对象,存储header信息 private static T GetDataCommonMethod<T>(string url, str ...

  3. Layui 2.0.0 正式发布:潜心之作,开箱即用的前端UI框架(确实很多内容)

    Hi,久违了.处暑逼近之际,潜水半年的 layui 是时候出来透透气了.我们带来的是全新的 2.0 版本,一次被我们定义为“破茧重生”的倾情之作.如果你已曾用过 layui,你将真正感受到一次因小而大 ...

  4. App.xaml介绍

    在App.xaml.cs中指定 public App () { InitializeComponent(); MainPage = new XamarinDemo.MainPage(); } 同时,这 ...

  5. JS顶级对象window

    <script type="text/javascript">        var num = 100;         alert(num);       wind ...

  6. xadmin下设置“use_bootswatch = True”无效解决方法

    from xadmin import viewsimport xadmin class BaseSetting(object): enable_themes=True use_bootswatch=T ...

  7. 图像滤镜艺术---(Punch Filter)交叉冲印滤镜

    原文:图像滤镜艺术---(Punch Filter)交叉冲印滤镜 (Punch Filter)交叉冲印滤镜 本文介绍一种交叉冲印效果的代码实现,至于原理,不在累赘,直接看代码:  int f_TPun ...

  8. 微信小程序把玩(二十)slider组件

    原文:微信小程序把玩(二十)slider组件 slider滑动组件用的不太多,在其他平台反正我是用的不多 主要属性: wxml <slider max="100" step= ...

  9. Redis实现关注关系

    最近使用关系型数据库实现了用户之间的关注,于是思考换一种思路,使用Redis实现用户之间的关注关系. 综合考虑了一下Redis的几种数据结构后,觉得可以用集合实现一下. 假设"我" ...

  10. WP8.1使用HttpClient类

    Uri uri = new Uri("http://www.cnsos.net/weburl/index.htm", UriKind.Absolute); HttpClient m ...