Java接口Lock有三个实现类:ReentrantLock、ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock。Lock接口提供了比使用synchronized更广泛的锁操作。

ReentrantLock是一个可重入的互斥锁。重入的含义是:当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会被阻塞。但是如果某个线程试图获得一个已经由它自己持有的锁时,这个请求是会成功的。"重入"意味着获取锁的操作的粒度是"线程",而不是"调用"。重入的一种实现方式就是,为每个锁关联一个获取计数值和一个所有者线程。当计数值为0时,这个锁就被认为是没有被任何线程持有。当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取到的计数值置为1.如果同一个线程再次获取这个锁,计数值将被递增,而当线程退出同步代码块时,计数器会相应地递减。当计数值为0时,这个锁将被释放。

对于ReentrantLock锁将由最近成功获得锁,并且没有释放该锁的线程所拥有。当锁没有被另外一个线程所拥有时,调用lock的线程将会成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。

ReentrantLock基础API

  1. lock() 获取锁

    加锁,如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为1。

    如果当前线程之前已经获取到了该锁,则将保持计数加1,并且该方法立即返回。

    如果该锁已经被另一个线程保持,则该线程不可被调度(即当前线程处于阻塞状态)直到该线程获取到锁,并且在获取到锁后,将保持计数设置为1。

  2. unlock释放锁

    试图释放锁。如果当前线程是此锁所有者,则将保持计数减1。如果保持计数器现在为0,则释放该属锁。如果当前线程不是此锁的持有者,则抛出IllegalMonitorStateException。

private Lock lock = new ReentrantLock() ;
public void await() {
try {
lock.lock();//加锁
} finally {
lock.unlock();//释放锁
}
}
  1. trylock()
  • 仅在调用时锁未被另一个线程保持的情况下,才获取锁。

  • 如果该锁没有被另一个线程保持,并且立即返回 true 值,则将锁的保持计数设置为 1。即使已将此锁设置为使用公平排序策略,但是调用 tryLock() 仍将 立即获取锁(如果有可用的),而不管其他线程当前是否正在等待该锁。在某些情况下,此“闯入”行为可能很有用,即使它会打破公平性也如此。如果希望遵守此锁的公平设置,则使用 tryLock(0, TimeUnit.SECONDS) ,它几乎是等效的(也检测中断)。

  • 如果当前线程已经保持此锁,则将保持计数加 1,该方法将返回 true。

  • 如果锁被另一个线程保持,则此方法将立即返回 false 值。

  1. tryLock(long timeout, TimeUnit unit)
  • 如果锁在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁。

  • 为了使用公平的排序策略,如果其他线程已经获取此锁,并且还有其他线程都在等待该锁,则立刻不会获取一个可用的锁,而公平的和其他线程进行等待锁分配。这与trylock方法相反。如果想使用一个允许闯入公平锁的定时tryLock,那么可以将定时形式和不定时形式组合在一起使用:

if(lock.tryLock() || lock.tryLock(timeout,uniy)) {
//.....
}
  1. lockInterruptibly

    如果当前线程未被中断,则获取锁。
  • 如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为1。
  • 如果该线程已经保持此锁,则将保持计数加1,并且该方法立即返回。
  • 如果该锁已经被其他线程保持,则等待;等待过程中,如果被其他线程打算,则抛出InterrupterException,并且中断该线程。
  • 在具体业务里,因为此方法是一个显示中断点,所以要优先考虑响应中断,而不是响应锁的普通获取或重入获取。

总结

  • lock --> 无限锁 调用后一直阻塞直到获得锁。
  • tryLock --> 拿到锁就返回true,不然就返回false;带有时间限制的tryLock(),拿不到锁,就等待一段时间,超时返回false。与while配合,可以实现轮询锁。
  • lockInterruptibly --> 调用后如果没有获取到锁会一直阻塞,阻塞过程中会接受中断信号。

参考原文地址

  1. Java中Lock,tryLock,lockInterruptibly有什么区别?

ReentrantLock 学习的更多相关文章

  1. ReentrantLock学习

    对于并发工作,你需要某种方式来防止两个任务访问相同的资源,至少在关键阶段不能出现这种冲突情况.防止这种冲突的方法就是当资源被一个任务使用时,在其上加锁.在前面的文章--synchronized学习中, ...

  2. java并发之ReentrantLock学习理解

    简介 java多线程中可以使用synchronized关键字来实现线程间同步互斥,但在jdk1.5中新增加了ReentrantLock类也能实现同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定 ...

  3. ReentrantLock 学习笔记

    有篇写的很不错的博客:https://blog.csdn.net/aesop_wubo/article/details/7555956    基于JDK1.8 参考着看源码 ,弄清楚lock()和un ...

  4. ReentrantLock学习笔记

    参考:https://www.jianshu.com/p/4358b1466ec9 前言: 先来想象一个场景:手把手的进行锁获取和释放,先获得锁A,然后再获取锁B,当获取锁B后释放锁A同时获取锁C,当 ...

  5. Java并发编程总结3——AQS、ReentrantLock、ReentrantReadWriteLock(转)

    本文内容主要总结自<Java并发编程的艺术>第5章——Java中的锁. 一.AQS AbstractQueuedSynchronizer(简称AQS),队列同步器,是用来构建锁或者其他同步 ...

  6. Java并发编程总结3——AQS、ReentrantLock、ReentrantReadWriteLock

    本文内容主要总结自<Java并发编程的艺术>第5章——Java中的锁. 一.AQS AbstractQueuedSynchronizer(简称AQS),队列同步器,是用来构建锁或者其他同步 ...

  7. ThreadLocal使用和原理简析

    1. 解决共享资源冲突 对于并发工作,需要某种方式来防止两个任务同时访问相同的资源,至少在关键阶段不能出现这种冲突情况. 方法之一就是当资源被一个任务使用时,在其上加锁.第一个访问某项资源的任务必须锁 ...

  8. JUC之AQS

    AbstractQueuedSynchronizer(AQS) AQS是并发容器里的同步器,从jdk1.5开始引入了并发包,java.util.concurrent,提供了一个基于first in f ...

  9. ReentrantLock原理学习

    上文我们学习了ReentrantLock的基本用法,在最后我们留下了一个问题,ReentrantLock获取的锁是什么锁呢?本文我们就从源码的角度来一探究竟.本文涉及到的源码对应JDK版本为1.8. ...

随机推荐

  1. Codevs1169:传纸条——题解

    题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就 ...

  2. BZOJ4105 [Thu Summer Camp 2015]平方运算 【线段树】

    题目链接 BZOJ4105 题解 平方操作orz,虽说应该是线段树,但是不会维护啊QAQ 小瞧一眼题解... 平方成环?环长\(lcm\)小于\(60\)? 果然还是打表找规律题.... 那就很好做了 ...

  3. POJ.1006 Biorhythms (拓展欧几里得+中国剩余定理)

    POJ.1006 Biorhythms (拓展欧几里得+中国剩余定理) 题意分析 不妨设日期为x,根据题意可以列出日期上的方程: 化简可得: 根据中国剩余定理求解即可. 代码总览 #include & ...

  4. linux下,手动切换jdk

    1.首先将自定义的jdk目录安装到alternatives中 seven@ThinkPad:~/srcAndroid/src4..4_r1$ sudo update-alternatives --in ...

  5. bzoj 1564 [NOI2009]二叉查找树 区间DP

    [NOI2009]二叉查找树 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 906  Solved: 630[Submit][Status][Discu ...

  6. JQuery学习三(隐式迭代和节点遍历)

    在JQuery中根据id获取控件,如果输入id错误是不报错的. 必要时可以通过写判断语句进行判断是否id写错 <!DOCTYPE html> <html xmlns="ht ...

  7. win下删除oracle

    关掉oralce服务. 具体方式有两种: 1.命令行下使用命令关闭服务:net stop OracleServiceORCL ,ORCL是我的实例名字,换成你的) 2.运行services.msc到系 ...

  8. UVA 1363 Joseph's Problem

    https://vjudge.net/problem/UVA-1363 n 题意:求 Σ  k%i i=1 除法分块 如果 k/i==k/(i+1)=p 那么 k%(i+1)=k-(i+1)*p= k ...

  9. 洛谷 3029 [USACO11NOV]牛的阵容Cow Lineup

    https://www.luogu.org/problem/show?pid=3029 题目描述 Farmer John has hired a professional photographer t ...

  10. HDU 5643 King's Game | 约瑟夫环变形

    经典约瑟夫环 }; ; i<=n; i++) { f[i] = (f[i-] + k) % i; } 变形:k是变化的 #include <iostream> #include &l ...