可重入和不可重入的概念是这样的:当一个线程获得了当前实例的锁,并进入方法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. Headless Chrome入门

    原文地址:Getting Started with Headless Chrome  By EricBidelman  Engineer @ Google working on web tooling ...

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

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

  3. BackgroundWorker使用

    using System.ComponentModel; private BackgroundWorker worker;  worker = new BackgroundWorker(); work ...

  4. jvm常用参数设置 专题

    在jdk8中 -Xms2g不合法,能通过的:-Xms2G #!/bin/bash JAVA_OPTS="-Xms4G -Xmx4G -XX:+HeapDumpOnOutOfMemoryErr ...

  5. 【C#】list 去重

    原文:[C#]list 去重 Enumerable.Distinct 方法 是常用的LINQ扩展方法,属于System.Linq的Enumerable方法,可用于去除数组.集合中的重复元素,还可以自定 ...

  6. 图像滤镜艺术---Photoshop实现Instagram Amaro滤镜特效

    原文:图像滤镜艺术---Photoshop实现Instagram Amaro滤镜特效 本文是我收集的一些使用Photoshop来实现Instagram滤镜的一些内容,在这里跟大家分享一下,这些效果是完 ...

  7. adb 命令连接指定设备

    试用条件: 当有多个设备online时: 步骤: 1. 通过adb devices命令获取所有online设备的serial number C:\Users\Administrator>adb ...

  8. TP5.0中使用trace调试

    1.在项目 的配置文件config.php 配置, 2.在程序中使用trace: 3.在浏览器网页上打开 得到如下图所示:点击 “用户变量”,即可查看使用trace输出的变量 或者我们使用 trace ...

  9. 微信小程序把玩(二十七)audio组件

    原文:微信小程序把玩(二十七)audio组件 音频播放已经封装的很好!只需配合属性设置即可! (method和data配合使用) 主要属性: wxml <audio action="{ ...

  10. 零元学Expression Blend 4 - Chapter 36 来玩捉迷藏吧!!!看看ScrollBar的Disabled与Hidden之差异

    原文:零元学Expression Blend 4 - Chapter 36 来玩捉迷藏吧!!!看看ScrollBar的Disabled与Hidden之差异 本次要针对Disabled以及Hidden作 ...