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.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...
随机推荐
- Django学习路20_流程复习
视频链接 https://www.bilibili.com/video/BV1rx411X717?p=21 千锋教育出品的 Django 课程 2020-05- ...
- 7.18 NOI模拟赛 因懒无名 线段树分治 线段树维护直径
LINK:因懒无名 20分显然有\(n\cdot q\)的暴力. 还有20分 每次只询问一种颜色的直径不过带修改. 容易想到利用线段树维护直径就可以解决了. 当然也可以进行线段树分治 每种颜色存一下直 ...
- 2020牛客暑假多校训练营 第二场 E Exclusive OR FWT
LINK:Exclusive OR 没做出 原因前面几篇说过了. 根据线性基的知识容易推出 不超过\(w=log Mx\)个数字即可拼出最大值 其中Mx为值域. 那么考虑w+2个数字显然也为最大值.. ...
- 5.4 省选模拟赛 修改 线段树优化dp 线段树上二分
LINK:修改 题面就不放了 大致说一下做法.不愧是dls出的题 以前没见过这种类型的 不过还是自己dp的时候写丑了. 从这道题中得到一个结论 dp方程要写的优美一点 不过写的过丑 优化都优化不了. ...
- duoxiao OJ #910 【高手训练】【动态规划】梦中漫步 期望 LCA
LINK:梦中漫步 当然也可以去一本通的Oj/loj上交(loj可能没有.. 期望好题.期望和dp往往是在一起的. 前置知识:1. 期望是线性可加的.2.和的期望等于期望的和. 从u出发每次随机选一条 ...
- 关于bin文件写法及导入
正常的python项目,打开看到的应该是一个个文件包,不同的功能模块放在不同的包里面: 通常是bin目录下的bin.py是程序的入口,下面的bin.py如何导入main.py并执行呢:
- python3.5 continue和break 项目:买房分期付款(2)
#案例:买房分期付款24万(10年期限) i=1#定义年份sum1=0while i<=10: print("第",i,"年到了......") if i ...
- 小伙子自从学会用Python爬取岛国“动作”电影,身体一天不如一天
在互联网的世界里,正确的使用VPN看看外面的世界,多了解了解世界的发展.肉身翻墙后,感受一下外面的肮脏世界.墙内的朋友叫苦不迭,由于某些原因,VPN能用的越来越少.上周我的好朋友狗子和我哭诉说自己常用 ...
- 07-NABCD项目分析
时 间:2020.3.31 参加人员:向瑜.赵常恒.刘志霄 讨论记录内容: NABCD模型 ·N(need)-向瑜 你的创意解决了用户的什么需求? 1. 随时随地记录个人收支的明细,清楚明白的知 ...
- jQuery 多库共存
多库共存 问题概述 jQuery使用$作为标识符,随着jQuery的流行,其他js的库也会用$作为标识符,这样就会引起冲突 需要一个解决方案 让jQuery和其他的JS ...