新事物的出现要不是替代老事物,要么就是对老事物的补充

JUC 的 locks 就是对 synchronized 的补充

一、synchronized 有不足

  1. 从开始竞争锁 到拿到锁这段时间,调用线程一直是阻塞状态,啥都干不了
  2. 已经占有的资源也释放不了,别的线程也无法获得;这种不可抢占的情况,更容易带来死锁(死锁产生的原理就是:我占着你要用的资源不给你,你却不能抢)
  3. 只有一个条件变量(条件等待队列),用于线程间的协调、通信

二、改进意见

采用更多的措施以避免死锁 :

  1. 不能抢占 变为 可抢占,占用部分资源的线程进一步申请其他资源时

    • 如果能快速申请到,就申请
    • 如果不能快速申请到,可以主动释放它占有的资源
  2. 使用者自己可创建多个条件变量,用于线程间的协调、通信。

三、可抢占的方法论

3.1 能够响应中断

synchronized 的问题是:持有锁 A 后,如果尝试获取锁 B 失败,那么线程就进入阻塞状态,一旦发生死锁,就没有任何机会来唤醒阻塞的线程。但如果阻塞状态的线程能够响应中断信号,也就是说当我们给阻塞的线程发送中断信号的时候,能够唤醒它,那它就有机会释放曾经持有的锁 A。这样就破坏了不可抢占条件了。

3.2 支持超时

如果线程在一段时间之内没有获取到锁,不是进入阻塞状态,而是返回一个错误,那这个线程也有机会释放曾经持有的锁。这样也能破坏不可抢占条件。

3.3 非阻塞地获取锁

如果尝试获取锁失败,并不进入阻塞状态,而是直接返回,那这个线程也有机会释放曾经持有的锁。这样也能破坏不可抢占条件。

四、可抢占的实现 - JUC 的 locks

// 支持中断的API
void lockInterruptibly() throws InterruptedException;
// 支持超时的API
boolean tryLock(long time, TimeUnit unit)  throws InterruptedException;
// 支持非阻塞获取锁的API
boolean tryLock();
复制代码

五、多个 Condition(条件变量或条件等待队列)

等效于管程中的条件变量,条件变量用于线程间的同步。通过java.util.concurrent.locks.Lock#newCondition()来创建,每个 Condition 都具有一个 waitSet;这样锁对象就具备了多个waitSet; Condition 提供了以下方法:用于线程的协作(线程等待/激活)。

//线程加入此条件变量的等待队列;类似Object.wait();使用时也要放到while循环体内。
java.util.concurrent.locks.Condition#await()
java.util.concurrent.locks.Condition#awaitUninterruptibly()
java.util.concurrent.locks.Condition#awaitNanos()
java.util.concurrent.locks.Condition#await(long, java.util.concurrent.TimeUnit)
java.util.concurrent.locks.Condition#awaitUntil()
//激活此条件变量中的一个线程;类似Object.notify()
java.util.concurrent.locks.Condition#signal()
//激活此条件变量中的所有线程;类似Object.notifyAll()
java.util.concurrent.locks.Condition#signalAll()
复制代码

java doc 示例:一个有界缓冲,两个条件等待队列,分别被生产者线程和消费者线程来使用。

  • 生产者线程在 notFull 条件队列中等待;意思为生产者线程要阻塞等待,直到 有界缓冲不是满的,才能 put
  • 消费者线程在 notEmpty 条件队列中等待;意思为消费者线程要阻塞等待,直到有界缓冲不是空的,才能 take
class BoundedBuffer {final Lock lock = new ReentrantLock();final Condition notFull  = lock.newCondition();final Condition notEmpty = lock.newCondition();final Object[] items = new Object[100];int putptr, takeptr, count;public void put(Object x) throws InterruptedException {lock.lock();try {while (count == items.length)notFull.await();items[putptr] = x;if (++putptr == items.length) putptr = 0;++count;notEmpty.signal();} finally {lock.unlock();}}public Object take() throws InterruptedException {lock.lock();try {while (count == 0)notEmpty.await();Object x = items[takeptr];if (++takeptr == items.length) takeptr = 0;--count;notFull.signal();return x;} finally {lock.unlock();}}
}
复制代码

六、JUC中locks的使用规范

6.1 保证锁的释放

 Lock l = ...;l.lock();try {// access the resource protected by this lock} finally {l.unlock();}
复制代码
 Lock lock = ...;if (lock.tryLock()) {try {// manipulate protected state} finally {lock.unlock();}} else {// perform alternative actions}
复制代码

6.2 循环体中使用 await()

while (XXX)condition.await();
复制代码

6.3 同步代码块中使用 await()

必须先持有锁

 l.lock();try {...while (XXX)condition.await();...} finally {l.unlock();}

既生 synchronized 何生 JUC 的 显式 locks ?相关推荐

  1. JAVA显式锁,各种锁分类

    显示锁优势 使用Java内置锁时,不需要通过Java代码显式地对同步对象的监视器进行抢占和释放,这些工作由JVM底层完成,而且任何一个Java对象都能作为一个内置锁使用,所以Java的对象锁使用起来非 ...

  2. Java多线程---线程通信(wait,notifyAll,生产者消费者经典范式,owner wait set,自定义显式锁BooleanLock)

    转自:https://blog.csdn.net/qq_35995514/article/details/91128585 1 学习内容 notifyAll 生产者.消费者经典范式 线程休息室 wai ...

  3. 原创 | 既生synchronized,何生volatile?!

    △Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 225篇原创分享 作者 l Hollis 来源 l Hollis(ID:hollischuang) 在我的博客和公众号中, ...

  4. 既生synchronized,何生volatile

    在作者博客和公众号(Hollis)中,发表过很多篇关于并发编程的文章,之前的文章中我们介绍过了两个在Java并发编程中比较重要的两个关键字:synchronized和volatile 我们简单回顾一下 ...

  5. 既生synchronized,何生volatile (synchronized与volatile的区别)

    既生synchronized,何生volatile (synchronized与volatile的区别) 我们知道,synchronized和volatile两个关键字是Java并发编程中经常用到的两 ...

  6. java 内置锁_深入理解java内置锁(synchronized)和显式锁(ReentrantLock)

    synchronized 和 Reentrantlock 多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两种同 ...

  7. 深入浅出 Babel 下篇:既生 Plugin 何生 Macros

    接着上篇文章: <深入浅出 Babel 上篇:架构和原理 + 实战 ????> 欢迎转载,让更多人看到我的文章,转载请注明出处 这篇文章干货不少于上篇文章,这篇我们深入讨论一下宏这个玩意  ...

  8. 小学生计算机舞蹈,最近“泼水成画”很火?舞蹈生VS体育生,看到计算机:你是来添乱的?...

    最近泼水拍照非常的流行,不知道大家在私底下有没有关注过这个视频,而且在这个视频中,这些花放在水里确实也特别的好看,接下来就一起来看一下,不同的学生拍出来的泼水照片都是什么样的. 首先大家看到的就是舞蹈 ...

  9. 既生瑜何生亮 access_token VS refresh_token

    中国有句老话, 既生瑜何生亮, 既然有我周瑜在世, 为什么老天还要一个诸葛亮啊? 同样的, 众所周知, 在 OAuth 2.0 授权协议中, 也有两个令牌 token , 分别是 access_tok ...

最新文章

  1. CMake入门指南-编译教程
  2. CSS box-shadow 盒子阴影属性
  3. JDK11的新特性:新的HTTP API
  4. 书评:JBoss AS 7:配置,部署和管理
  5. 既稳又狂!黑鲨游戏手机2官宣发布时间:3月18日北京见
  6. Eclipse 编码常用技巧【不断补充完善】
  7. thinkphp学习总结
  8. microsoft azure Media Services 媒体服务解决方案
  9. intersystem-M语言基础语法
  10. Keras:我的第一个神经网络二分类模型
  11. 免费可商用图片素材网站,建议收藏
  12. 微信查询四六级成绩代码
  13. SPP Net 空间金字塔池化(Spatial Pyramid Pooling, SPP)原理
  14. 公安人员审问四名窃贼嫌疑犯
  15. python中怎么计数_python怎么实现计数?
  16. MySQL备份和恢复:mysqldump工具用法详述
  17. Halcon API
  18. Git 如何带你回到过去
  19. 利用jacob操作word文档
  20. WPF 鼠标双击命令

热门文章

  1. 广远社团队给大家分享这些年经历的网赚时代
  2. 腾讯T1~T9级别工程师分别需要具备哪些能力你知道吗?
  3. flutter 局部状态和全局状态区别_Android 开发者遇到 5G、AI,写给 Android 开发者的 Flutter 指南
  4. Retrofit网络请求数据的使用
  5. 关于java项目与web项目中lib包的那点事
  6. getenv putenv setenv和unsetenv详解
  7. ODBC数据源:没有ORACLE用户DSN,也没有驱动程序?
  8. 游戏美术设计外包哪家比较好
  9. web安全:XSS测试平台使用教程
  10. CPU中的MESI协议(Intel)