package lock.lock;import java.util.Random;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** 描述:     用tryLock来避免死锁*/
public class TryLockDeadlock implements Runnable {int flag = 1;static Lock lock1 = new ReentrantLock();static Lock lock2 = new ReentrantLock();public static void main(String[] args) {TryLockDeadlock r1 = new TryLockDeadlock();TryLockDeadlock r2 = new TryLockDeadlock();r1.flag = 1;r1.flag = 0;new Thread(r1).start();new Thread(r2).start();}@Overridepublic void run() {for (int i = 0; i < 100; i++) {if (flag == 1) {try {if (lock1.tryLock(800, TimeUnit.MILLISECONDS)) {try {System.out.println("线程1获取到了锁1");Thread.sleep(new Random().nextInt(1000));if (lock2.tryLock(800, TimeUnit.MILLISECONDS)) {try {System.out.println("线程1获取到了锁2");System.out.println("线程1成功获取到了两把锁");break;} finally {lock2.unlock();}} else {System.out.println("线程1获取锁2失败,已重试");}} finally {lock1.unlock();Thread.sleep(new Random().nextInt(1000));}} else {System.out.println("线程1获取锁1失败,已重试");}} catch (InterruptedException e) {e.printStackTrace();}}if (flag == 0) {try {if (lock2.tryLock(3000, TimeUnit.MILLISECONDS)) {try {System.out.println("线程2获取到了锁2");Thread.sleep(new Random().nextInt(1000));if (lock1.tryLock(800, TimeUnit.MILLISECONDS)) {try {System.out.println("线程2获取到了锁1");System.out.println("线程2成功获取到了两把锁");break;} finally {lock1.unlock();}} else {System.out.println("线程2获取锁1失败,已重试");}} finally {lock2.unlock();Thread.sleep(new Random().nextInt(1000));}} else {System.out.println("线程2获取锁2失败,已重试");}} catch (InterruptedException e) {e.printStackTrace();}}}}
}

ReentrantLock的tryLock方法是对Lock接口的tryLock实现

应用场景

非阻塞的场景,允许某些任务不执行(比如防止重复提交业务),或超时不执行(比如防止资源等待队列溢出)等

不带参数的 tryLock

public boolean tryLock() {return sync.nonfairTryAcquire(1);
}

实现比较简单,内部调用sync#nonfairTryAcquire方法,该方法前篇分析lock方法的时候已经解析过了在此不做赘述

带超时和支持中断响应的 tryLock

/*** Acquires the lock if it is free within the given waiting time and the* current thread has not been {@linkplain Thread#interrupt interrupted}.*(在指定的时间内获取锁如果锁未被其他线程持有,并且这个线程没有被中断)* <p>If the lock is available this method returns immediately* with the value {@code true}.*(如果锁是可用的这个方法会立刻返回true)* If the lock is not available then* the current thread becomes disabled for thread scheduling* purposes and lies dormant until one of three things happens:* (如果锁是不可用的那么当前线程将不可用对于线程调度,并且会休眠直到1件或3件事情发生)* <ul>* <li>The lock is acquired by the current thread; or* <li>Some other thread {@linkplain Thread#interrupt interrupts} the* current thread, and interruption of lock acquisition is supported; or* <li>The specified waiting time elapses* </ul>*(这个锁被当前线程持有;或者其他的线程中断了当前线程,并且锁的中断是被支持的;或者指定的等待时间超时)* <p>If the lock is acquired then the value {@code true} is returned.*(如果这个锁被获取那么将返回true)* <p>If the current thread:* <ul>* <li>has its interrupted status set on entry to this method; or* <li>is {@linkplain Thread#interrupt interrupted} while acquiring* the lock, and interruption of lock acquisition is supported,* </ul>* then {@link InterruptedException} is thrown and the current thread's* interrupted status is cleared.* 如果线程被中断将抛出InterruptedException异常* <p>If the specified waiting time elapses then the value {@code false}* is returned.* If the time is* less than or equal to zero, the method will not wait at all.*(如果指定的等待时间到了还未获取到锁将返回false,如果指定的时间少于或者等于0,方法将不会等待)* <p><b>Implementation Considerations</b>*(实现的注意事项)* <p>The ability to interrupt a lock acquisition in some implementations* may not be possible, and if possible may* be an expensive operation.* The programmer should be aware that this may be the case. An* implementation should document when this is the case.*(在某些实现中中断锁获取的能力可能不可能,并且可能的话是一个昂贵的操作。程序员应该意识到情况可能是这样的。一个在这种情况下,实现应该记录下来。)* <p>An implementation can favor responding to an interrupt over normal* method return, or reporting a timeout.*(一个实现可以响应一个中断,或者报告超时)* <p>A {@code Lock} implementation may be able to detect* erroneous use of the lock, such as an invocation that would cause* deadlock, and may throw an (unchecked) exception in such circumstances.* The circumstances and the exception type must be documented by that* {@code Lock} implementation.*(实现可能会检测到锁的错误使用,例如可能导致死锁的调用,并可能在这种情况下引发(未经检查的)异常。这种情况和异常类型必须由{@code lock}实现记录)* @param time the maximum time to wait for the lock (获取锁的最大等待时间)* @param unit the time unit of the {@code time} argument (时间单位)* @return {@code true} if the lock was acquired and {@code false}*         if the waiting time elapsed before the lock was acquired*(如果锁被获取了返回true,如果等待时间超时还未获取则返回false)* @throws InterruptedException if the current thread is interrupted*         while acquiring the lock (and interruption of lock*         acquisition is supported)*(当前线程被中断了需要返回InterruptedException当获取锁的时候(并且锁的获取中断是被支持的))*/boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

查看ReentrantLock的实现

public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}

sync#tryAcquireNanos 调用的是父类AbstractQueuedSynchronizer的tryAcquireNanos方法

    /*** Attempts to acquire in exclusive mode, aborting if interrupted,* and failing if the given timeout elapses.  Implemented by first* checking interrupt status, then invoking at least once {@link* #tryAcquire}, returning on success.  Otherwise, the thread is* queued, possibly repeatedly blocking and unblocking, invoking* {@link #tryAcquire} until success or the thread is interrupted* or the timeout elapses.  This method can be used to implement* method {@link Lock#tryLock(long, TimeUnit)}.** @param arg the acquire argument.  This value is conveyed to*        {@link #tryAcquire} but is otherwise uninterpreted and*        can represent anything you like.* @param nanosTimeout the maximum number of nanoseconds to wait* @return {@code true} if acquired; {@code false} if timed out* @throws InterruptedException if the current thread is interrupted*/public final boolean tryAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {//中断检测if (Thread.interrupted())throw new InterruptedException();//step1. 调用tryAcquire先尝试获取锁,如果失败则调用doAcquireNanosreturn tryAcquire(arg) ||doAcquireNanos(arg, nanosTimeout);}

AbstractQueuedSynchronizer#doAcquireNanos

    /*** Acquires in exclusive timed mode.** @param arg the acquire argument* @param nanosTimeout max wait time* @return {@code true} if acquired*/private boolean doAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (nanosTimeout <= 0L)return false;//计算出到期时间final long deadline = System.nanoTime() + nanosTimeout;//新增独占节点final Node node = addWaiter(Node.EXCLUSIVE);boolean failed = true;try {//反复重试直到成功获取锁或者超时返回falsefor (;;) {final Node p = node.predecessor();//该节点的前节点是头节点则尝试获取锁if (p == head && tryAcquire(arg)) {setHead(node);p.next = null; // help GCfailed = false;return true;}//剩余时间nanosTimeout = deadline - System.nanoTime();if (nanosTimeout <= 0L)//超时返回falsereturn false;//shouldParkAfterFailedAcquire 判断是否需要阻塞线程 并且剩余时间大于 spinForTimeoutThreshold (默认1000)if (shouldParkAfterFailedAcquire(p, node) &&nanosTimeout > spinForTimeoutThreshold)LockSupport.parkNanos(this, nanosTimeout);//中断检测if (Thread.interrupted())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}}

tryLock尝试获取锁相关推荐

  1. php 批量更新死锁,php – 在尝试获取锁定时,哪个查询导致死锁;尝试重新启动事务...

    我无法弄清楚哪个Query在尝试获取锁定时导致死锁;尝试重新启动事务. 我的 mysql包装器有以下几行 if (mysql_errno($this->conn) == 1213) { $thi ...

  2. java锁源码分析-1获取锁的过程

    这篇文章(包括后边两篇)是六月份写的,写完后由于工作较忙,草稿一致没时间修改,今天偶尔翻到,担心哪天弄丢了,于是先以草稿的形式发布,内容有瑕疵,等以后有时间再修复. 解读类的结构 首先来看类的继承关系 ...

  3. java 中lock,java中lock获取锁的四种方法

    在java接口中会存放着许多方法,方便线程使用时的直接调用.对于lock接口大家都不陌生,我们已经初步对概念进行了理解.那么在获取锁的方法上想必还不是很清楚.下面我们就lock获取锁的四种方法分别进行 ...

  4. 代码演示:获取锁时被中断

    lockInterruptibly() lockInterruptibly():相当于tryLock(long time, TimeUnit unit)把超时时间设置为无限,在等待锁的过程中,线程可以 ...

  5. 多线程系列学习:AQS(一)获取锁

    AQS是AbstractQueuedSynchronizer的简称,juc包下锁的实现,基本上需要借助于AQS的功能,如下图所示: 通过继承结构,可以看到,常用的可重入锁ReentrantLock,以 ...

  6. Lock锁及获取锁的四种方法

    为什么使用LOCK? LOCK锁 LOCK锁的上锁与解锁 为什么使用LOCK? 传统的Synchronized锁有非常多的缺点: 锁的唤醒和阻塞代价较高,线程的阻塞和唤醒,操作系统需要在用户态与内核态 ...

  7. 解决多线程安全问题-无非两个方法synchronized和lock 具体原理以及如何 获取锁AQS算法 (百度-美团)

    解决多线程安全问题-无非两个方法synchronized和lock 具体原理以及如何 获取锁AQS算法 (百度-美团) 参考文章: (1)解决多线程安全问题-无非两个方法synchronized和lo ...

  8. Java多线程学习十六:读写锁 ReadWriteLock 获取锁有哪些规则

    读写锁 ReadWriteLock 获取锁有哪些规则呢? 在没有读写锁之前,我们假设使用普通的 ReentrantLock,那么虽然我们保证了线程安全,但是也浪费了一定的资源,因为如果多个读操作同时进 ...

  9. 从服务器获取文件错误,在尝试获取许可证时出现无法从许可证服器上读取数据的错误信息...

    Problem [Simplified Chinese] 在尝试获取许可证时遇到FLEXlm -16 "无法从许可证服务器上读取数据"的错误信息. Symptom 完整的错误信息如 ...

最新文章

  1. python采用Basemap绘制完美中国地图(包括绘制边界框,随机点等)
  2. Linux下服务器端开发流程及相关工具介绍(C++)
  3. 在Flutter中设置更好的Logging的指南
  4. 这10个人,总是牛逼的无话可说
  5. 代码大全和新月神话_神话般的代码
  6. 自动部署war包脚本
  7. C语言优先队列作用,C语言实现优先队列(priority queue)
  8. 30岁以后的人生,如何来逆袭?
  9. HttpClient 模拟登录网易微博
  10. HTML5生日祝福网页制作 (粉色系列为你定制) HTML+CSS+JavaScript
  11. win10 ping网络计算机,如何使用PING命令测试win10的网络速度
  12. 一键查询网站服务器归属地,一文搞定3种批量查询手机归属地的方法
  13. (附源码)火车票订票系统 毕业设计 171538
  14. 古诗文登录验证码识别及登录
  15. 年度总结 | 回味2022不平凡的一年
  16. springboot--入门程序实现CRUD操作
  17. java编写的公共钥匙盒_公共钥匙盒.java
  18. 教父马云的经典语录汇总
  19. 输入手机号查询信息C语言,简单个人电话号码查询系统.doc
  20. python成绩查询系统_python成绩查询

热门文章

  1. Date日期类型的绑定
  2. 安装完成后在命令行运行bash时报错0x80070057
  3. 如何理解苹果iOS版PhoneGap原理分析
  4. 依赖注入及AOP简述(六)——字符串请求模式 .
  5. HALCON基础知识
  6. 弹性盒模型--新版与旧版比较(1)
  7. 决定以太坊未来的三个关键扩容项目
  8. 设置Eclipse RCP程序的外观和首选项
  9. 使用supervisor启动hbase
  10. 【转】C#调用WebService实例和开发