ReentrantLock 和 synchronized 的区别:

1.ReentrantLock 不需要代码块,在开始的时候lock,在结束的时候unlock 就可以了。

但是要注意,lock 是有次数的,如果连续调用了两次lock,那么就需要调用两次unlock。否则的话,别的线程是拿不到锁的。

    /*** 很平常的用锁 没有感觉reentrantlocak 的强大** 如果当前线程已经拿到一个锁了 那么再次调用 会里面返回true* 当前线程的锁数量是 2个**/private void normalUse() {ReentrantLock reentrantLock =  new ReentrantLock();new Thread("thread1"){@Overridepublic void run() {super.run();LogToFile.log(TAG,"thread1 lock");reentrantLock.lock();reentrantLock.lock();LogToFile.log(TAG,"thread1 getHoldCount:"  + reentrantLock.getHoldCount() );try {LogToFile.log(TAG,"thread1 run");Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}//如果说你的线程占了两个锁 一个没有释放 其他线程都拿不到这个锁//上面lock 了两次 这里需要unLock 两次reentrantLock.unlock();reentrantLock.unlock();LogToFile.log(TAG,"thread1 unlock");}}.start();new Thread("thread2"){@Overridepublic void run() {super.run();LogToFile.log(TAG,"thread2 lock");reentrantLock.lock();LogToFile.log(TAG,"thread2 run");reentrantLock.unlock();LogToFile.log(TAG,"thread2 unlock");}}.start();}

ReentrantLock trylock()

ReentrantLock trylock 会尝试去拿锁,如果拿得到,就返回true, 如果拿不到就返回false.这个都是立马返回,不会阻塞线程。
如果当前线程已经拿到锁了,那么trylock 会返回true.

    /*** trylock 不管能不能拿到锁 都会里面返回结果 而不是等待* tryLock 会破坏ReentrantLock 的 公平机制* 注意 如果没有拿到锁 执行完代码之后不要释放锁,* 否则会有exception**/private void UseTryLock() {ReentrantLock reentrantLock =  new ReentrantLock();new Thread("thread1"){@Overridepublic void run() {super.run();LogToFile.log(TAG,"thread1 lock");reentrantLock.lock();try {LogToFile.log(TAG,"thread1 run");Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}reentrantLock.unlock();LogToFile.log(TAG,"thread1 unlock");}}.start();new Thread("thread2"){@Overridepublic void run() {super.run();LogToFile.log(TAG,"thread2 tryLock");boolean success = reentrantLock.tryLock();LogToFile.log(TAG,"thread2 run");if (success) {reentrantLock.unlock();LogToFile.log(TAG,"thread2 unlock");//    java.lang.IllegalMonitorStateException//        at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:123)//        at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1235)//        at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:429)}}}.start();}

ReentrantLock .tryLock(5, TimeUnit.SECONDS)

ReentrantLock 可以指定,尝试去获取锁,等待多长时间之后,如果还获取不到,那么就放弃。

    /*** tryLock(5, TimeUnit.SECONDS)* 如果5s之后 还拿不到锁  那么就不再堵塞线程,也不去拿锁了 执行执行下面的代码了*/private void UseTryLockWhitTime() {ReentrantLock reentrantLock =  new ReentrantLock();new Thread("thread1"){@Overridepublic void run() {super.run();LogToFile.log(TAG,"thread1 lock");reentrantLock.lock();try {LogToFile.log(TAG,"thread1 run");Thread.sleep(1000 * 10);} catch (InterruptedException e) {e.printStackTrace();}reentrantLock.unlock();LogToFile.log(TAG,"thread1 unlock");}}.start();new Thread("thread2"){@Overridepublic void run() {super.run();LogToFile.log(TAG,"thread2 tryLock");boolean success = false;try {success = reentrantLock.tryLock(5, TimeUnit.SECONDS);LogToFile.log(TAG,"thread2 run");if (success) {reentrantLock.unlock();LogToFile.log(TAG,"thread2 unlock");//    java.lang.IllegalMonitorStateException//        at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:123)//        at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1235)//        at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:429)}} catch (InterruptedException e) {e.printStackTrace();}}}.start();}

ReentrantLock .lock();

一旦调用了ReentrantLock .lock() ,如果你的线程被其他线程interrupt,那么你的线程并不会interrupt,而是继续等待锁。

    /*** lockInterruptibly() 和  lock 的区别是* 如果当前线程被Interrupt 了,那么lockInterruptibly 就不再等待锁了。直接会抛出来一个异常给你处理* 如果是lock 的话 就算 线程被其他的线程lockInterrupt 了,不管用,他还会继续等待锁*/private void UseLockIntercepter() {ReentrantLock reentrantLock =  new ReentrantLock();Thread thread = new Thread("thread1") {@Overridepublic void run() {super.run();LogToFile.log(TAG, "thread1 lock");reentrantLock.lock();LogToFile.log(TAG, "thread1 run");if (reentrantLock.getHoldCount() != 0) {reentrantLock.unlock();}LogToFile.log(TAG, "thread1 unlock");}};new Thread("thread2"){@Overridepublic void run() {super.run();LogToFile.log(TAG,"thread2 tryLock");boolean success = false;try {reentrantLock.lock();thread.start();thread.interrupt();success = reentrantLock.tryLock(5, TimeUnit.SECONDS);LogToFile.log(TAG,"thread2 run");if (success) {reentrantLock.unlock();reentrantLock.unlock();LogToFile.log(TAG,"thread2 unlock");//    java.lang.IllegalMonitorStateException//        at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:123)//        at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1235)//        at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:429)}} catch (InterruptedException e) {e.printStackTrace();}}}.start();}

ReentrantLock .lockInterruptibly();

如果当前线程调用lockInterruptibly 这个方法去获取锁,当其他的线程把你的线程给interrupt 之后,那么你的线程就不再等待锁了,执行下面的代码。

    /*** lockInterruptibly() 和  lock 的区别是* 如果当前线程被Interrupt 了,那么lockInterruptibly 就不再等待锁了。直接会抛出来一个异常给你处理* 如果是lock 的话 就算 线程被其他的线程lockInterrupt 了,不管用,他还会继续等待锁*/private void UseLockIntercepter2() {ReentrantLock reentrantLock =  new ReentrantLock();Thread thread = new Thread("thread1") {@Overridepublic void run() {super.run();LogToFile.log(TAG, "thread1 lock");try {reentrantLock.lockInterruptibly();} catch (InterruptedException e) {e.printStackTrace();LogToFile.log(TAG, "thread1 lock InterruptedException ");}LogToFile.log(TAG, "thread1 run");if (reentrantLock.getHoldCount() != 0) {reentrantLock.unlock();}LogToFile.log(TAG, "thread1 unlock");}};new Thread("thread2"){@Overridepublic void run() {super.run();LogToFile.log(TAG,"thread2 tryLock");boolean success = false;try {reentrantLock.lock();thread.start();thread.interrupt();success = reentrantLock.tryLock(5, TimeUnit.SECONDS);LogToFile.log(TAG,"thread2 run");if (success) {reentrantLock.unlock();reentrantLock.unlock();LogToFile.log(TAG,"thread2 unlock");//    java.lang.IllegalMonitorStateException//        at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:123)//        at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1235)//        at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:429)}} catch (InterruptedException e) {e.printStackTrace();}}}.start();}

ReentrantLock newCondition()使用:

condition. 的await 相当于 object 的wait 方法,就是等待其他线程唤醒,但是调用之前必须要reentrantLock.lock(); 一下,不然会抛异常。

    /*** tryLock(5, TimeUnit.SECONDS)* 如果5s之后 还拿不到锁  那么就不再堵塞线程,也不去拿锁了 执行执行下面的代码了*/private void UseCondition() {ReentrantLock reentrantLock =  new ReentrantLock();Condition condition = reentrantLock.newCondition();Thread thread = new Thread("thread1") {@Overridepublic void run() {super.run();try {reentrantLock.lock();LogToFile.log(TAG, "thread1 wait");//await 其实是会释放锁的 其他的线程可以拿到锁 然后signal  不然的话岂不是要卡死?condition.await();LogToFile.log(TAG, "thread1 run");Thread.sleep(1000 * 3);condition.signalAll();reentrantLock.unlock();} catch (InterruptedException e) {e.printStackTrace();}LogToFile.log(TAG, "thread1 unlock");}};thread.start();Thread thread1 = new Thread("thread2") {@Overridepublic void run() {super.run();//调用signal 之前一定要lockreentrantLock.lock();//就算没有人调用await 那么signal 方法也不会有什么问题condition.signal();try {LogToFile.log(TAG, "thread2 wait");condition.await();LogToFile.log(TAG, "thread2 run");} catch (InterruptedException e) {e.printStackTrace();}reentrantLock.unlock();}};thread1.start();}

Object wait方法使用:

wait 方法调用之前也要synchronized 一个锁。

    /*** 使用wait*/private void UseWait() {ReentrantLock reentrantLock =  new ReentrantLock();Condition condition = reentrantLock.newCondition();new Thread("thread1"){@Overridepublic void run() {super.run();try {synchronized (condition) {LogToFile.log(TAG,"thread1 wait");condition.wait();}LogToFile.log(TAG,"thread1 run");Thread.sleep(1000 * 10);synchronized (condition) {condition.notifyAll();}} catch (InterruptedException e) {e.printStackTrace();}LogToFile.log(TAG,"thread1 unlock");}}.start();new Thread("thread2"){@Overridepublic void run() {super.run();synchronized (condition) {condition.notify();}try {LogToFile.log(TAG,"thread2 wait");synchronized (condition){condition.wait();}LogToFile.log(TAG,"thread2 run");} catch (InterruptedException e) {e.printStackTrace();}}}.start();}

synchronized

synchronized 锁等待的线程,当被其他线程interrupt 的时候,并不会停止。

/*** synchronized 的锁,不能被中断*/
public void testSyncInter(){Object lock = new Object();Thread thread = new Thread("thread1") {@Overridepublic void run() {super.run();synchronized (lock) {LogToFile.log(TAG, "thread1 lock");LogToFile.log(TAG, "thread1 run");}LogToFile.log(TAG, "thread1 unlock");}};new Thread("thread2"){@Overridepublic void run() {super.run();synchronized (lock) {LogToFile.log(TAG,"thread2 start");thread.start();thread.interrupt();}LogToFile.log(TAG,"thread2 run");}}.start();
}

BlockingQueue 就是使用ReentrantLock 实现的阻塞队列:

    /*** BlockingQueue  会阻塞当前的线程  等着其他线程放数据*/public void testArrayBlockQueue(){BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(4);new Thread("thread1"){@Overridepublic void run() {super.run();try {LogToFile.log(TAG,"thread1 take");blockingQueue.take();LogToFile.log(TAG,"thread1 take  get");} catch (InterruptedException e) {e.printStackTrace();}}}.start();new Thread("thread2"){@Overridepublic void run() {super.run();try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}try {LogToFile.log(TAG,"thread2 put");//put 会阻塞 但是add 不会blockingQueue.put(2);} catch (InterruptedException e) {e.printStackTrace();}}}.start();}

ArrayBlockingQueue 源码解析:

下面的代码,可以看到ArrayBlockingQueue 创建了ReentrantLock ,以及两个condition

/** Main lock guarding all access */final ReentrantLock lock;/** Condition for waiting takes */private final Condition notEmpty;/** Condition for waiting puts */private final Condition notFull;public ArrayBlockingQueue(int capacity, boolean fair) {if (capacity <= 0)throw new IllegalArgumentException();this.items = new Object[capacity];lock = new ReentrantLock(fair);notEmpty = lock.newCondition();notFull =  lock.newCondition();}

当我们往里面放元素的时候,我们会对notFull 进行等待,因为队列不是空的了。

当出队列的时候,notFull.signal(); 也就是当前的队列不是满的了,可以放元素进去了。

    /*** Inserts the specified element at the tail of this queue, waiting* for space to become available if the queue is full.** @throws InterruptedException {@inheritDoc}* @throws NullPointerException {@inheritDoc}*/public void put(E e) throws InterruptedException {checkNotNull(e);final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {while (count == items.length)notFull.await();enqueue(e);} finally {lock.unlock();}}private E dequeue() {// assert lock.getHoldCount() == 1;// assert items[takeIndex] != null;final Object[] items = this.items;@SuppressWarnings("unchecked")E x = (E) items[takeIndex];items[takeIndex] = null;if (++takeIndex == items.length)takeIndex = 0;count--;if (itrs != null)itrs.elementDequeued();notFull.signal();return x;}

当我们往里面取元素的时候,如果队列是空的了,那么notEmpty 就要等待,当enqueue一个元素的时候,notEmpty 不是空就唤醒,那么take 就可以执行去拿元素了。

    public E take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {while (count == 0)notEmpty.await();return dequeue();} finally {lock.unlock();}}private void enqueue(E x) {// assert lock.getHoldCount() == 1;// assert items[putIndex] == null;final Object[] items = this.items;items[putIndex] = x;if (++putIndex == items.length)putIndex = 0;count++;notEmpty.signal();}

Java ReentrantLock 详解相关推荐

  1. Java 多线程详解(三)------线程的同步

    Java 多线程详解(一)------概念的引入:https://blog.csdn.net/weixin_39816740/article/details/80089790 Java 多线程详解(二 ...

  2. 【运维能力提升计划-3】Java多线程详解

    Java多线程详解 学习链接 Java.Thread 线程简介 线程 进程 多线程 线程实现 Thread 继承Thread类 调用run方法只有主线程一个线程,调用start方法生成子线程与主线程并 ...

  3. Apache Thrift - java开发详解

    2019独角兽企业重金招聘Python工程师标准>>> Apache Thrift - java开发详解 博客分类: java 架构 中间件 1.添加依赖 jar <depen ...

  4. Java泛型详解-史上讲解最详细的,没有之一

    目录 1. 概述 2. 一个栗子 3. 特性 4. 泛型的使用 4.1 泛型类 4.2 泛型接口 4.3 泛型通配符 4.4 泛型方法 4.4.1 泛型方法的基本用法 4.4.2 类中的泛型方法 4. ...

  5. Java虚拟机详解----JVM常见问题总结

    [正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾 ...

  6. java 泛型详解、Java中的泛型方法、 java泛型详解

    本文参考java 泛型详解.Java中的泛型方法. java泛型详解 概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用. 什么是泛型?为什么要使用泛型? 泛型,即& ...

  7. 最详细的java泛型详解

    来源:最详细的java泛型详解 对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下. 本文参考java 泛型详解.Java中的泛型方法. ja ...

  8. Java异常详解及如何处理

    来源:Java异常详解及如何处理 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言 ...

  9. Java基础——Java NIO详解(一)

    一.基本概念 1.I/0简介 I/O即输入输出,是计算机与外界世界的一个借口.IO操作的实际主题是操作系统.在java编程中,一般使用流的方式来处理IO,所有的IO都被视作是单个字节的移动,通过str ...

最新文章

  1. 3项目在ie11浏览器打不开_Chrome/Safari都输了:新Edge浏览器率先实现100%支持HTML5...
  2. 计算机专业英语文章翻译,计算机专业英语英汉双语文章翻译
  3. 技术大牛养成指南,一篇不鸡汤的成功学实践
  4. 菜鸟学exchange之一:exchange邮件系统的简单安装和部署
  5. Reuse library debug in Chrome - phase2 handle success response (2)
  6. 洛谷 P1404 平均数
  7. 目录2. 计算机 13. 计算机智能 24. 软件 25. 操作系统 36. 互联网 37. 软件产业 38. 软件演示 49. 软件专利 410. 复杂性 411. 易用性
  8. C/C++学校运动会管理系统
  9. Smart Gesture/ATK could not open key,华硕触摸板安装报错,卸载Smart Gesture
  10. matlab怎么定义plot函数线的类型,matlabplot函数线型
  11. 【地平线旭日X3派试用体验】基于MIPI Camera的目标检测 web 端展示,全流程(第三节)
  12. Windows IIS服务器SSL数字证书安装指南
  13. Dva中在effects中获取state的值
  14. chown -R 用户名:组名 ./ 及 chown用法介绍
  15. 洗车Myjnie 题解
  16. fota 差分包_FOTA
  17. zookeeper集群搭建(三台服务)
  18. Sql Server2008安装图解
  19. 交互式shell和非交互式shell、登录shell和非登录shell
  20. 智源大会倒计时,参会大数据发布:实名注册超2万,名校名企知名机构云集,来自17个国家(附大会详细日程)...

热门文章

  1. 两个超长正整数的加法c语言,二个超长正整数的相加
  2. 压缩可以卸载吗_不可错过!螺杆压缩机故障分析详解(2)
  3. C++知识点10——函数指针
  4. HALCON识别数字ID
  5. ViSP中识别AprilTag的C++实例代码与运行结果
  6. java实例方法,Java实例和静态方法
  7. 河北高速盘点七大假牌假证违法案例:寒冬穿大裤衩开车
  8. Vue计算属性和监听属性
  9. nginx反向代理、负载均衡、动态请求
  10. html中,纯数字或纯英文的一串字符超出父容器不会折行显示,如何解决?