ReentrantLock是重入锁,它与synchronized很像,它是synchronized的加强版,因为它具有一些synchronized没有的功能。
下面我们看看两者的区别:
synchronized具有一定的局限性:

  • 当线程尝试获取锁的时候,如果获取不到锁会一直阻塞;
  • 如果获取锁的线程进入休眠或者阻塞,除非当前线程异常,否则其他线程尝试获取锁必须一直等待;
  • 是非公平的。

而ReentrantLock实现了AQS,可以完成下列功能:

  • 可中断响应;
  • 锁申请等待限时;
  • 公平锁;
  • 与Condition一起使用,实现synchronized与wait/notify的功能。

引入几个概念:
提到ReentrantLock,我们不得不明白几个概念:

  • 可重入锁。可重入锁是指同一个线程可以多次获取同一把锁。ReentrantLock和synchronized都是可重入锁。
  • 可中断锁。可中断锁是指线程尝试获取锁的过程中,是否可以响应中断。synchronized是不可中断锁,ReentrantLock则提供了中断功能。
  • 公平锁与非公平锁。公平锁是指多个线程必须按顺序,不许插队。非公平锁允许插队。synchronized是非公平锁,而ReentrantLock的默认实现是非公平锁,但是也可以设置为公平锁。
  • CAS,在前面已经提到。

使用示例
具体用法通过简单代码通过代码演示:

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo implements Runnable {
static ReentrantLock lock = new ReentrantLock();
static int count = 0; @Override
public void run() {
for (int i = 0; i < 10000; i++) {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
} } public static void main(String[] args) {
ReentrantLockDemo r = new ReentrantLockDemo();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
//结果输出:20000
}
}

通过ReentrantLock解决死锁问题:

import java.util.concurrent.locks.ReentrantLock;

public class KillDeadlockDemo implements Runnable {
static ReentrantLock lock1 = new ReentrantLock();
static ReentrantLock lock2 = new ReentrantLock();
int lock; public KillDeadlockDemo(int lock) {
super();
this.lock = lock;
} @Override
public void run() {
try {
if (lock == 1) {
lock1.lockInterruptibly();
Thread.sleep(500);
lock2.lockInterruptibly();
} else {
lock2.lockInterruptibly();
Thread.sleep(500);
lock1.lockInterruptibly();
}
} catch (InterruptedException e) {
} finally {
if (lock1.isHeldByCurrentThread()) {
lock1.unlock();
}
if (lock2.isHeldByCurrentThread()) {
lock2.unlock();
}
System.out.println(Thread.currentThread().getName() + "退出!");
} } public static void main(String[] args) {
KillDeadlockDemo kdd1 = new KillDeadlockDemo(1);
KillDeadlockDemo kdd2 = new KillDeadlockDemo(2);
Thread t1 = new Thread(kdd1);
Thread t2 = new Thread(kdd2);
t1.start();
t2.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.interrupt();
/*
*结果输出:
*Thread-1退出!
*Thread-0退出!
*/
    }
}

使用 tryLock()或者tryLock(long timeout, TimeUtil unit) 方法进行一次限时的锁等待,也可以解决死锁问题:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; public class TryLockDemo implements Runnable {
static ReentrantLock lock = new ReentrantLock(); @Override
public void run() {
try {
if (lock.tryLock(1, TimeUnit.SECONDS)) {
Thread.sleep(1100);
} else {
System.out.println(Thread.currentThread().getName() + "获取锁失败!释放");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
} public static void main(String[] args) {
TryLockDemo td = new TryLockDemo();
Thread thread1 = new Thread(td);
Thread thread2 = new Thread(td);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//结果输出:Thread-1获取锁失败!释放
}
}

公平锁演示:

import java.util.concurrent.locks.ReentrantLock;

public class FairLockDemo implements Runnable {
static ReentrantLock lock = new ReentrantLock(true); @Override
public void run() {
while (true) {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " get lock");
Thread.sleep(1000);
} catch (InterruptedException e) {
} finally {
lock.unlock();
}
}
} public static void main(String[] args) {
FairLockDemo fld = new FairLockDemo();
Thread t1 = new Thread(fld);
Thread t2 = new Thread(fld);
Thread t3 = new Thread(fld);
t1.start();
t2.start();
t3.start();
/*
*Thread-0 get lock
*Thread-1 get lock
*Thread-2 get lock
*Thread-0 get lock
*Thread-1 get lock
*Thread-2 get lock
*..........
*/
}
}

浅谈原理

请转到:https://www.cnblogs.com/ericz2j/p/13445822.html



Java多线程_ReentrantLock的更多相关文章

  1. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  2. Java多线程基础知识篇

    这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...

  3. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  4. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  5. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  6. Java多线程 2 线程的生命周期和状态控制

    一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...

  7. java 多线程 1 线程 进程

    Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报  分类: javaSE综合知识点(14)  版权声明:本文为博主原创文章,未经博 ...

  8. 一起阅读《Java多线程编程核心技术》

    目录 第一章 Java多线程技能 (待续...)

  9. 第一章 Java多线程技能

    1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...

随机推荐

  1. Django开发之Datetime类型JSON序列化时报错

    前提回顾 在进行django开发view视图时,如果数据库字段是 datetime类型,在JSON序列化返回时,会出现异常 异常现象 TypeError: Object of type datetim ...

  2. 第四章 常用API(上)

    4.1.Object类 描述:该类是所有类的最终根类 方法 描述 public boolean equals(Object obj) 表示某个其它对象是否"等于"此对象 publi ...

  3. Fortify Audit Workbench 笔记索引

    Password Management: Password in Configuration File(明文存储密码) https://www.cnblogs.com/mahongbiao/p/124 ...

  4. python基础day7_购物车实例

    print("欢迎光临") money = input("请输入您的金额:") shopping_car ={} li = [{"name" ...

  5. Skill 脚本演示 ycAutoSnap.skl

    https://www.cnblogs.com/yeungchie/ ycAutoSnap.skl 版图编辑中自动吸附 Path 的 "垂直线头",也可以批量对齐 Bus 走线,也 ...

  6. Typora + PicGo-Core + Custom Command 实现上传图片到图床

    教程参考 Typora+PicGo-Core(command line)+Gitee实现图片上传到图床 主要借鉴 picgo 操作命令 Typora + PicGo + Gitee 实现图片自动上传到 ...

  7. .NET三层架构各项目之间的引用关系及如何添加引用?

    1.1三层之间的引用 整个.NET框架的项目创建完成之后,在开发之前,还需要建立各个项目之间的引用关系,以便在编写C#业务逻辑代码时调用相关项目的类库. 1.1.1 引用关系规则 .NET三层架构中的 ...

  8. python2.4项目:快递计价程序

    #开发一个快递计价程序3kg以内:东三省.宁夏.海南.12元:新疆.西藏20元:港澳台.国外:不接受:其他10元.超过3kg的部分:东三省.宁夏.海南每公斤10元:新疆.西藏每公斤20元:港澳台.国外 ...

  9. 2020牛客多校第八场K题

    __int128(例题:2020牛客多校第八场K题) 题意: 有n道菜,第i道菜的利润为\(a_i\),且有\(b_i\)盘.你要按照下列要求给顾客上菜. 1.每位顾客至少有一道菜 2.给顾客上菜时, ...

  10. Python | 面试的常客,经典的生产消费者模式

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第23篇文章,我们来聊聊关于多线程的一个经典设计模式. 在之前的文章当中我们曾经说道,在多线程并发的场景当中,如果我 ...