美文网首页
java多线程(核心篇)第七章

java多线程(核心篇)第七章

作者: jiahzhon | 来源:发表于2020-01-03 15:57 被阅读0次

第七章 保障线程安全的设计技术(不必借助锁的情况下保障线程安全)

7.1 死锁
  1. 死锁是线程的一种常见活性故障。如果两个或者更多的线程因相互等待对方而被永远暂停(线程的生命周期状态为BLOCKED或者WAITING),那么我们就称这些线程产生了死锁。
  2. 死锁产生条件(所有条件同时成立)
    • 资源互斥。涉及的资源必须是独占的,即每个资源一次只能够被另一个线程使用。
    • 资源不可抢夺。涉及的资源只能够被其持有者(线程)主动释放,而无法被资源的持有者和申请者之外的第三方线程所抢夺(被动释放)。
    • 占用并等待资源。涉及的线程当前至少持有一个资源(资源A)并申请其他资源(资源B),而这些资源(资源B)恰好被其他线程持有。在这个资源等待的过程中,线程并不释放其已经持有的资源。
    • 循环等待资源。涉及的线程必须在等待别的线程持有的资源,而这些线程又反过来在等待第1个线程所持有的资源。
  3. 产生原因通常是锁的嵌套


    image.png
  4. 规避死锁方法。
    • 粗锁法。——使用粗粒度的锁代替多个锁。这样涉及线程都只需要申请一个锁从而避免了死锁。(避免了“占用并等待资源”和“循环等待资源”)。但是会降低并发性。
    • 锁排序法。——相关线程使用全局统一的顺序申请锁。那么让这些线程依照一个全局统一顺序去申请这些资源,就可以消除“循环等待资源”。


      image.png
    • 使用ReentrantLock.tryLock(long,TimeUnit)申请锁。允许我们为锁申请这个操作指定一个超时时间。在超时时间内,如果相应的锁申请成功,那么该方法返回true;如果在tryLock执行的那一刻相应的锁正被其他线程持有,那么该方法会使当前线程暂停,直到这个锁被申请成功(此时该方法返回true)或者等待时间超过指定的超时时间(此时该方法返回false)。因此,使用tryLock来申请锁可以避免一个线程无限制地等待另外一个线程持有的资源(消除“占用并等待资源”)。
    • 开放调用——更常见的导致死锁情况可能是一个方法在持有一个锁的情况下调用另外一个同步方法。所谓开放调用就是一个方法在调用外部方法的时候不持有任何锁。
  5. 死锁的自动恢复有赖于线程的中断机制。基本思想:定义一个工作者线程专门用于死锁检测与恢复。该线程定期检测系统中是否存在死锁,若检测到死锁,则随机选取一个死锁线程并给其发送中断,抛出InterruptedException。直到系统中不再存在死锁。
7.2 锁死
  1. 等待线程由于唤醒其所需的条件永远无法成立,或者其他线程无法唤醒这个线程而一直处于非运行状态(线程并未终止)导致其任务一直无法进展,那么我们就称这个线程被锁死。
7.3 线程饥饿
  1. 线程饥饿是指线程一直无法获得其所需的资源而导致其任务一直无法进展的一种活性故障。
7.4 活锁
  1. 活锁是指线程一直处于运行状态,但是其任务却一直无法进展的一种活性故障。产生活锁的线程一直在做无用功。

相关文章

网友评论

      本文标题:java多线程(核心篇)第七章

      本文链接:https://www.haomeiwen.com/subject/kwgzoctx.html