文章目录

死锁

概念

死锁示例

为什么会出现死锁呢?

如何解决死锁呢?

解决死锁代码实现

活锁

概念

活锁示例:

如何解决活锁呢?

饥饿

概念

如何解决饥饿呢?

死锁

概念

死锁:一组互相竞争资源的线程因互相等待,导致“永久”阻塞的现象。

说白了就是:两个线程互相持有对方所需的资源,互不释放且互相等待

死锁示例

/**

* 死锁

*

* @author m

*/

public class Account {

private int balances;

public static void main(String[] args) {

Account A = new Account();

Account B = new Account();

new Thread(() -> {

A.transfer(B, 100);

}, "线程1 ").start();

new Thread(() -> {

B.transfer(A, 100);

}, "线程2 ").start();

}

//转账

public void transfer(Account target, int money) {

//休眠(放大问题发生性)

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (this) {

System.out.println(Thread.currentThread().getName() + " 持有锁 " + this + ",等待锁" + target);

synchronized (target) {

System.out.println(Thread.currentThread().getName() + " 持有锁 " + target);

this.balances += money;

target.balances -= money;

System.out.println("转账结束");

}

}

}

}

执行结果

为什么会出现死锁呢?

假设线程T1执行转账A->B,线程T2执行转账B->A,两个线程同时执行synchronized (this)时,线程T1获取了A的锁,线程T2获取了B的锁,同时又执行到了synchronized (target)时,线程T1获取B锁时,发现B锁已经被线程T2持有,线程T1进入阻塞状态;与此同时,线程T2获取A锁时,发现A锁已经被线程T1持有,线程T2也进入阻塞状态。参考下图理解

如何解决死锁呢?

并发程序一旦死锁,一般没有特别好的方法,很多时候我们只能重启应用。因此,解决死锁问题最好的办法还是规避死锁。

那如何避免死锁呢?要避免死锁就需要分析死锁发生的条件,有个叫 Coffman 的牛人早就总结过了,只有以下这四个条件都发生时才会出现死锁:

互斥,共享资源 X 和 Y 只能被一个线程占用;

占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;

不可抢占,其他线程不能强行抢占线程 T1 占有的资源;

循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。

既然知道了出现死锁的必要条件,其实只要破坏其中一条就可避免死锁!

其中,互斥这个条件我们没有办法破坏,因为我们用锁为的就是互斥。不过其他三个条件都是有办法破坏掉的,到底如何做呢?

对于“占用且等待”这个条件,我们可以一次性申请所有的资源,这样就不存在等待了。

对于“不可抢占”这个条件,占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源,这样不可抢占这个条件就破坏掉了。

对于“循环等待”这个条件,可以按顺序申请资源来预防。所谓按序申请,是指资源是有线性顺序的,申请的时候可以先申请资源序号小的,再申请资源序号大的,这样线性化后自然就不存在循环了。

解决死锁代码实现

下面我只列出避免死锁的第三种方案按照顺序加锁,同时也是成本最低的。

//转账

public void transfer(Account target, int money) {

Account little; //id小的账户

Account big; //id大的账户

if (this.id < target.id) {

little = this;

big = target;

} else {

little = target;

big = this;

}

// 锁定id小的账户

synchronized (little) {

System.out.println(Thread.currentThread().getName() + " 持有锁 " + this + ",等待锁" + target);

// 锁定id大的账户

synchronized (big) {

System.out.println(Thread.currentThread().getName() + " 持有锁 " + target);

this.balances += money;

target.balances -= money;

System.out.println("转账结束");

}

}

}

活锁

概念

活锁:有时线程虽然没有发生阻塞,但仍然会存在执行不下去的情况。

说白了就是:两个线程因互相礼让,导致线程永远的礼让下去

例如:可以类比现实世界里的例子,路人甲从左手边出门,路人乙从右手边进门,两人为了不相撞,互相谦让,路人甲让路走右手边,路人乙也让路走左手边,结果是两人又相撞了。这种情况,基本上谦让几次就解决了,因为人会交流啊。可是如果这种情况发生在编程世界了,就有可能会一直没完没了地“谦让”下去,成为没有发生阻塞但依然执行不下去的“活锁”。

活锁示例:

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

/**

* 活锁

*

* @author m

*/

public class Account2 {

private int balances;

private final Lock lock = new ReentrantLock();

public static void main(String[] args) {

Account2 A = new Account2();

Account2 B = new Account2();

new Thread(() -> {

A.transfer(B, 100);

}, "线程1 ").start();

new Thread(() -> {

B.transfer(A, 100);

}, "线程2 ").start();

}

void transfer(Account2 target, int money) {

while (true) {

if (this.lock.tryLock()) {

System.out.println(Thread.currentThread().getName() + " 持有锁 " + this.lock + ",等待锁" + target.lock);

try {

if (tar.lock.tryLock()) {

System.out.println(Thread.currentThread().getName() + " 持有锁 " + target.lock);

try {

this.balances -= money;

tar.balances += money;

} finally {

tar.lock.unlock();

}

}

} finally {

this.lock.unlock();

}

}

}

}

}

如何解决活锁呢?

谦让时,尝试等待一个随机的时间就可以了。“等待一个随机时间”的方案虽然很简单,却非常有效,Raft 这样知名的分布式一致性算法中也用到了它。

例如上面的那个例子,路人甲走左手边发现前面有人,并不是立刻换到右手边,而是等待一个随机的时间后,再换到右手边;同样,路人乙也不是立刻切换路线,也是等待一个随机的时间再切换。由于路人甲和路人乙等待的时间是随机的,所以同时相撞后再次相撞的概率就很低了。

饥饿

概念

饥饿:线程因无法访问所需资源而无法执行下去的情况

说白了就是:假设有1万个线程,还没等前面的线程执行完,后面的线程就饿死了

如何解决饥饿呢?

下面提供了三种方案

保证资源充足

公平地分配资源

避免持有锁的线程长时间执行

这三个方案中,方案一和方案三的适用场景比较有限,因为很多场景下,资源的稀缺性是没办法解决的,持有锁的线程执行的时间也很难缩短。倒是方案二的适用场景相对来说更多一些。

开心一刻

两个老人去养老院。。。

70岁的老人进去了,90岁老人没进去。

工作人员:“对不起,大爷,我们不接受儿女健在的老人。您的资料显示,你有一个儿子。”

90岁老人:“操,刚刚进去的就是我儿子! ”

如果觉得不错,帮忙点个赞,您的点赞将是我的动力!

java避免活锁.死锁的解决,死锁 活锁 饥饿 出现原因及解决方案相关推荐

  1. linux下死锁怎么解决方法,死锁,解决死锁的4种基本方法

    死锁,解决死锁的4种基本方法 死锁 这个概念是操作系统里面很重要的内容,前阵子面试字节被问到了,太久没复习,面经变凉经. 死锁(Deadlock),又被翻译为死结.是操作系统或软件运行的一种状态,在多 ...

  2. java死锁_Java死锁原理,手写死锁,解决死锁

    死锁:多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,而导致两个或者多个线程都在等在对方释放资源. 都停止的情形.某一个同步块同时拥有两个以上对象的锁时,就会产生死锁问题. 手写 ...

  3. 线程死锁的成因?如何查找并定位死锁,解决死锁?这里教你几招~

    目录 什么是死锁? 死锁代码案例: 出现死锁的原因 教你如何定位死锁位置~ 死锁解决方法 什么是死锁? 死锁就是指线程t1要使用的资源被线程t2占用,线程t2想使用的资源被线程 t1占用,这就像两股绳 ...

  4. mysql死锁解决方法_mysql出现死锁的原因及解决方案

    mysql出现死锁的原因及解决方案 发布时间:2020-06-04 16:35:40 来源:51CTO 阅读:418 作者:三月 本文主要给大家介绍mysql出现死锁的原因及解决方案,文章内容都是笔者 ...

  5. 死锁的充分必要条件、死锁预防、死锁避免、死锁检测和解除

    2.19.2 死锁的条件 必要条件 互斥:一次只有一个进程可以使用一个资源 占有且等待:当进程等待其他资源时继续占有已有的资源 不可抢占:进程不能强行占有其他进程占有的进程 充分条件 循环等待:存在一 ...

  6. Java多线程闲聊(二):活锁和死锁

    Java多线程闲聊(二):活锁和死锁 这两个情况其实都是应该需要避免的情况,为了便于自己的回顾,我还是希望通过尽可能简单的表达来进行简要的归纳. 何谓死锁,就是正正紧紧按照Java的规范进行编程依然会 ...

  7. 死锁、活锁、饥饿定位死锁解决死锁

    文章目录 1. 死锁 2. 定位死锁 2.1 jstack工具使用 2.2 jconsole工具使用: 3. 解决死锁 3.1 哲学家就餐问题 4. 活锁 4.1 活锁原因 4.2 活锁解决 5. 饥 ...

  8. 死锁与活锁的区别,死锁与饥饿的区别?

    **死锁:**是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去. 产生死锁的必要条件: 1.互斥条件:所谓互斥就是进程在某一时间 ...

  9. Java 线程实例一(查看线程是否存活、获取当前线程名称、状态监测、线程优先级设置、死锁及解决方法、获取线程id、线程挂起)

    查看线程是否存活 以下实例演示了如何通过继承 Thread 类并使用 isAlive() 方法来检测一个线程是否存活: public class TwoThreadAlive extends Thre ...

最新文章

  1. FTP匿名登录或弱口令漏洞及服务加固
  2. 提高Service提高进程优先级别,不被系统容易杀死
  3. 简述java的异常处理机制_简述java异常处理机制
  4. 如何设置Android Studio绘制布局时的视图
  5. 原生js实现简单的svg编辑器
  6. 【密码学】基于 SM3 算法的 HMAC 快速实现
  7. ADB连接手机和简单命令
  8. 偏移量范围计算机组成,计算机组成原理-郑秋梅 - 习题
  9. 组合数有关的一些求和公式
  10. .net MVC全局定时器执行作业
  11. 地震后的重建!——AD灾难恢复!
  12. httpwatch9.1 安装包
  13. Pomodoro方法
  14. 基于Arduino开发板的文本转语音(TTS)转换器
  15. 基于Arduino+机智云的阳台生态控制系统设计
  16. 图片太大不要慌,简单的调整图片大小
  17. oracle错误号提示ORA-
  18. 雅马哈机器人编程讲解_雅马哈机器人RCX编程手册
  19. 在360新员工入职培训上的讲话
  20. Java数字位数不足前面补0的几种办法

热门文章

  1. 这么好用的低延时直播,网易云信将它开源了
  2. 音视频应用开发系列文章目录
  3. 【渝粤题库】国家开放大学2021春2755财政与金融(农)题目
  4. word中图片不能完全显示的解决办法
  5. 计算机屏幕灯,玩电脑必须要有的神器——屏幕挂灯
  6. c语言弹琴小程序,非常好玩的弹钢琴小程序.doc
  7. [翻译] [LaTeX] Undefined control sequence
  8. 万物皆可虚拟?虚拟电厂了解一下
  9. 谈谈新的前端框架 Svelte 和现代前端框架的特点
  10. 火焰特效消防安全视频PR片头模板