【JUC】3.ReentrantLock
ReentrantLock实现Lock接口,所以先看下Lock接口:
public interface Lock {
// 获得锁
void lock();
// 获得锁
void unlock();
// lock非阻塞版本,成功返回true
boolean tryLock();
// 添加尝试时间,时间到返回false
boolean tryLock(long time, TimeUnit unit)
// 返回一个监视器对象
Condition newCondition();
}
再来看ReentrantLock的常用API:
public class ReentrantLock implements Lock,Serializable {
// 构造器,可以实现公平锁
public ReentrantLock()
public ReentrantLock(boolean fair)
public void lock()
// 可中断锁
public void lockInterruptibly()
// 可轮询的锁获取,有返回值。获取成功返回true;获取失败,返回false,线程不会阻塞、
public boolean tryLock()
public boolean tryLock(long timeout, TimeUnit unit)
// 返回一个监视器对象
Condition newCondition();
}
ReentrantLock的使用方法分为这么几块:
1. 可重入锁的实现;
2. 公平锁与非公平锁;
3. 配合Condition实现的选择性通知, condition实现阻塞队列,这两个可以视为同一块;
4. tryLock的实现;
5.生产者消费者模式实现,如果用Condition实现这个模式,其实跟实现阻塞队列是类似的;
同样也可以单纯使用阻塞队列实现生产者消费者模式;
可重入锁的实现
可以再次获取自己的内部锁,即:一个线程获取某对象锁,在没有释放此对象锁的同时,可以再次获得此锁;
锁释放请务必在finally中进行
public class ReentrantLockTest {
private static final Lock lock = new ReentrantLock();
public static void test1() {
lock.lock();
try {
System.out.println("已进入test_1");
test2();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void test2() {
lock.lock();
try {
System.out.println("已进入test_2");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
公平锁与非公平锁
只要在构造器中传入true,实现方面没什么好说的;
非公平锁下的后来线程可以插队,减少了一定的线程上下文切换
公平锁下后来的线程必须排队等待锁的释放,多进行了一步判断,线程挂起的几率比较高,所以效率略低
满足FIFO(先进先出队列)
非公平锁虽然效率高,但是有可能出现线程饿死的情况,比如客户端一直无法获得服务,所以,服务器一般用公平锁实现;
配合Condition实现的选择性通知
这个可以跟实现阻塞队列一起说了,感觉代码层面,基本一致;
public class MyBlockingQueue<T> {
private int limit;
private final Lock lock = new ReentrantLock();
private final Condition Full = lock.newCondition();
private final Condition Empty = lock.newCondition();
private List<T> queue = new LinkedList<>();
public MyBlockingQueue(int limit) {
this.limit = limit;
}
public void enqueue(T item) throws InterruptedException {
lock.lock();
try {
// 队列满
while (queue.size() == limit) {
Full.await();
}
queue.add(item);
Empty.signal();
} finally {
lock.unlock();
}
}
public T dequeue(T item) throws InterruptedException {
lock.lock();
try {
// 队列空
while (queue.size() == 0) {
Empty.await();// 将当前线程阻塞在Empty监视器下
}
Full.signal(); // 叫醒Full监视器下阻塞的线程
return queue.remove(0);
} finally {
lock.unlock();
}
}
}
tryLock的实现
tryLock方法可以无参,可以传入等待时间;
public class MytryLock {
private static final Lock lock = new ReentrantLock();
// 由于是否获得锁不确定,所以设置标志位判断
private static boolean isLocked = false;
public static void test() {
try {
if (lock.tryLock(1000, TimeUnit.MILLISECONDS)) {
// trylock返回true,即拿到锁
isLocked = true;
System.out.println(Thread.currentThread().getName() + "拿到锁!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
/**
* 没拿到锁,可以让线程继续做别的事
* 不会阻塞
*/
System.out.println(Thread.currentThread().getName() + "没拿到锁!");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (isLocked == true)
lock.unlock();
}
}
}
生产者消费者模式实现
同condition实现阻塞队列;
queue就是生产者的仓库对象;
enqueue就是生产;
dequeue就是消费;
【JUC】3.ReentrantLock的更多相关文章
- 【1】【JUC】JDK1.8源码分析之ReentrantLock
概要: ReentrantLock类内部总共存在Sync.NonfairSync.FairSync三个类,NonfairSync与FairSync类继承自Sync类,Sync类继承自AbstractQ ...
- 【JUC】JDK1.8源码分析之ArrayBlockingQueue(三)
一.前言 在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看Arra ...
- 【1】【JUC】JDK1.8源码分析之ArrayBlockingQueue,LinkedBlockingQueue
概要: ArrayBlockingQueue的内部是通过一个可重入锁ReentrantLock和两个Condition条件对象来实现阻塞 注意这两个Condition即ReentrantLock的Co ...
- 【JUC】阻塞队列&生产者和消费者
阻塞队列 线程1往阻塞队列添加元素[生产者] 线程2从阻塞队列取出元素[消费者] 当队列空时,获取元素的操作会被阻塞 当队列满时,添加元素的操作会被阻塞 阻塞队列的优势:在多线程领域,发生阻塞时,线程 ...
- 【JUC】JDK1.8源码分析之ReentrantLock(三)
一.前言 在分析了AbstractQueuedSynchronier源码后,接着分析ReentrantLock源码,其实在AbstractQueuedSynchronizer的分析中,已经提到过Ree ...
- 【JUC】4.Synchronized与ReentrantLock对比
与synchronized相同,ReentrantLock也是一种互斥锁: synchronized与ReentrantLock的对比: 都是可重入锁 可以再次获取自己的内部锁,即:一个线程获取某对象 ...
- 【1】【JUC】Condition和生产者消费者模型
本篇文章将介绍Condition的实现原理和基本使用方法,基本过程如下: 1.Condition提供了await()方法将当前线程阻塞,并提供signal()方法支持另外一个线程将已经阻塞的线程唤醒. ...
- 【JUC】synchronizated和lock的区别&新lock的优势
原始构成 synchronized是关键字,属于JVM层面 javap -c 的结果显示 synchronized是可重入锁 11:是正常退出 17:是异常退出[保证不产生死锁和底层故障] Lock是 ...
- 【JUC】JUC锁框架综述
一.前言 在分析完了集合框架后,很有必要接着分析java并发包下面的源码,JUC(java.util.concurrent)源码也是我们学习Java迈进一步的重要过程.我们分为几个模块进行分析,首先是 ...
随机推荐
- 【转】23 个安卓重难点突破,带你吃透 Service 知识点「长达 1W+ 字」
前言 学 Android 有一段时间了,想必不少人也和我一样,平时经常东学西凑,感觉知识点有些凌乱难成体系.所以趁着这几天忙里偷闲,把学的东西归纳下,捋捋思路. 这篇文章主要针对 Service 相关 ...
- Win10 LTSC 2019 安装和卸载 linux 子系统
一.开启 二.下载 https://docs.microsoft.com/zh-cn/windows/wsl/install-manual 手动下载适用于 Linux 的 Windows 子系统发 ...
- linux系统(centos6)的目录结构
/bin:bin是Binary的缩写, 这个目录存放着最经常使用的命令. /boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件. /dev :dev是Device( ...
- SQL 对decimal类型转换为int类型
) AS INT) CountQty select ISNULL( CAST(E.Qty AS INT),0 ) FROM OrderDetail E 空值 需要默认为0 即可
- [转]MathJax与LaTex公式简介
链接地址:https://www.cnblogs.com/linxd/p/4955530.html
- 阿里云k8s部署zookeeper集群
1. 阿里云k8s创建有状态应用 StatefulSet , 选择使用模板创建 可以创建自定义模板 apiVersion: apps/v1 kind: StatefulSet metadata: c ...
- VisualStudio开发UE4工程设置
转自:http://wangjie.rocks/2016/06/24/ue4-vs-setup/ 推荐插件 Visual Assist X C++ 代码高亮 UnrealVS Extension UE ...
- H2数据库介绍
H2数据库是一个开源的关系型数据库. H2是一个采用java语言编写的嵌入式数据库引擎,只是一个类库(即只有一个 jar 文件),可以直接嵌入到应用项目中,不受平台的限制 应用场景: 可以同应用程序打 ...
- py库:pdfminer3k、docx。(PDFf转word)
安装pdfminer模块: pip install pdfminer3k 安装docx模块: https://www.lfd.uci.edu/~gohlke/pythonlibs/ 下载 pytho ...
- [New!!!]欢迎大佬光临本蒟蒻的博客(2019.11.27更新)
更新于2019.12.22 本蒟蒻在博客园安家啦!!! 本蒟蒻的博客园主页 为更好管理博客,本蒟蒻从今天开始,正式转入博客园. 因为一些原因,我的CSDN博客将彻底不会使用!!!(带来不便,敬请谅解) ...