Java多线程_ReentrantLock
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的更多相关文章
- 40个Java多线程问题总结
前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...
- Java多线程基础知识篇
这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程--让主线程等待子线程执行完毕
使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...
- Java多线程 2 线程的生命周期和状态控制
一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...
- java 多线程 1 线程 进程
Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报 分类: javaSE综合知识点(14) 版权声明:本文为博主原创文章,未经博 ...
- 一起阅读《Java多线程编程核心技术》
目录 第一章 Java多线程技能 (待续...)
- 第一章 Java多线程技能
1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...
随机推荐
- 360随身WiFi3:纯净版无线网卡驱动下载及安装教程(Windows10版本)
对于不带无线网卡的台式机,买一个360随身WiFi当无线网卡是很省钱的方法.但是这个随身WiFi3用的芯片较为奇葩,Win10下不太好找驱动.什么,你问我为啥不用360官网上的驱动?那个“驱动”装了之 ...
- PHP is_resource() 函数
is_resource() 函数用于检测变量是否为资源类型. PHP 版本要求: PHP 4, P+-HP 5, PHP 7高佣联盟 www.cgewang.com 语法 bool is_resour ...
- JWT到底是个什么鬼?
前面一篇我们了解了微服务安全认证架构是如何演进而来的,但是发现v2.5架构仍然较重,有没有轻量级一点的方法呢?其实业界早已有了实践,它就是基于JWT的安全认证架构.JWT到底是个什么鬼呢?本篇为你解答 ...
- 原生JS 实现点击按钮创建元素
要求: 点击按钮,随机生成一个20px-100px宽度正方形,随机颜色,随机位置,不能出可视区域外 思路:(1)创建按钮,为按钮添加事件侦听 (2)触发事件,创建一个元素 (3)设置元素样式,包括大小 ...
- duoxiao OJ #910 【高手训练】【动态规划】梦中漫步 期望 LCA
LINK:梦中漫步 当然也可以去一本通的Oj/loj上交(loj可能没有.. 期望好题.期望和dp往往是在一起的. 前置知识:1. 期望是线性可加的.2.和的期望等于期望的和. 从u出发每次随机选一条 ...
- 《Head First 设计模式》:单件模式
正文 一.定义 单件模式确保一个类只有一个实例,并提供一个全局访问点. 要点: 定义持有唯一单件实例的类变量. 私有化构造,避免其他类产生实例. 对外提供获取单件实例的静态方法. 二.实现步骤 1.创 ...
- 【leetcode每日两题】-Day1-简单题
1. 两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数组中同一个元素 ...
- CF习题集一
CF习题集一 一.CF915E Physical Education Lessons 题目描述 \(Alex\)高中毕业了,他现在是大学新生.虽然他学习编程,但他还是要上体育课,这对他来说完全是一个意 ...
- Python 教你自动发微博,每日一句英语
作者:周萝卜 最近在研究用 Python 来制作各个类别的机器人,今天先来分享一个自动发布新浪微博的机器人. 基本思路 其实要实现一个简单的自动发布微博机器人还是不难的,只需要每天按时找好要发布的素材 ...
- linux系统中SSH免密设置报错
执行 ssh-add ~/.ssh/msi_rsa 时报下面错误 Could not open a connection to your authentication agent. 解决办法: 执行命 ...