在java并发编程领域已经有技术大咖总结出了发生死锁的条件,只有四个条件都发生时才会出现死锁:

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

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

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

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

  只要能破坏其中一个,就可以成功避免死锁的发生,因为对于共享资源我们要得就是互斥的效果,所以第一个条件是无法破坏的,所以可以从下面三个条件出手,具体实现方式:

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

  

class Allocator{
//通过破坏占有且等待条件避免死锁现象的发生
private List<Object> als = new ArrayList<>();
//一次申请所有的资源
synchronized boolean apply(Object from, Object to){
if (als.contains(from) || als.contains(to)){
//只要存在一个账户被其他的业务锁定则无法完成转账业务
return false;
}else {
als.add(from);
als.add(to);
}
return true;
}
//归还资源
synchronized void free(Object from,Object to){
als.remove(from);
als.remove(to);
}
}
class Account {
//actr应该为单例
private Allocator actr;
private int balance;
//转账
void transfer(Account target, int amt){
//一次性申请转出和转入账户,直到成功
while (!actr.apply(this,target));
try{
//锁定转出账户
synchronized (this){
//锁定转入账户
synchronized (target){
if (this.balance > amt){
this.balance -= amt;
target.balance += amt;
}
}
}
}finally {
actr.free(this, target);
}
}
}

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

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

    class Accounts{
private int id;
private int balance;
//转账
void transfer(Accounts target,int amt){
Accounts left = this;
Accounts right = target;
if (this.id > target.id){
left = target;
right = this;
}
//锁定序号小的账户
synchronized (left){
//锁定序号大的账户
synchronized (right){
if (this.balance > amt){
this.balance -= amt;
target.balance += amt;
}
}
}
}
}

java并发编程如何预防死锁的更多相关文章

  1. Java并发编程实战 04死锁了怎么办?

    Java并发编程文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 前提 在第三篇 ...

  2. 【Java并发编程】:死锁

    当线程需要同时持有多个锁时,有可能产生死锁.考虑如下情形: 线程A当前持有互斥所锁lock1,线程B当前持有互斥锁lock2.接下来,当线程A仍然持有lock1时,它试图获取lock2,因为线程B正持 ...

  3. Java并发编程实战 05等待-通知机制和活跃性问题

    Java并发编程系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 Java并发编程实 ...

  4. Java并发编程原理与实战十一:锁重入&自旋锁&死锁

    一.锁重入 package com.roocon.thread.t6; public class Demo { /* 当第一个线程A拿到当前实例锁后,进入a方法,那么,线程A还能拿到被当前实例所加锁的 ...

  5. java并发编程笔记(八)——死锁

    java并发编程笔记(八)--死锁 死锁发生的必要条件 互斥条件 进程对分配到的资源进行排他性的使用,即在一段时间内只能由一个进程使用,如果有其他进程在请求,只能等待. 请求和保持条件 进程已经保持了 ...

  6. 【转】关于Java并发编程的总结和思考

    一.前言 就是想学习Java并发编程了,所以转载一下这篇认为还不错的博客~ 二.正文 编写优质的并发代码是一件难度极高的事情.Java语言从第一版本开始内置了对多线程的支持,这一点在当年是非常了不起的 ...

  7. Java并发编程系列-(7) Java线程安全

    7. 线程安全 7.1 线程安全的定义 如果多线程下使用这个类,不过多线程如何使用和调度这个类,这个类总是表示出正确的行为,这个类就是线程安全的. 类的线程安全表现为: 操作的原子性 内存的可见性 不 ...

  8. 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport

    在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...

  9. 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock

    ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...

随机推荐

  1. js-用判断音乐或图片是否加载完成的方式来控制页面的现实

    判断页面加载,加完完成后,内容页显示,加载条隐藏 百度搜索方法很多,大多都是: document.onreadystatechange = function() //当页面加载状态改变的时候执行fun ...

  2. springboot启动时报错 错误: 找不到或无法加载主类 com.xxx.xxx.Application

    1. Q1 错误: 找不到或无法加载主类 com.xxx.xxx.Application 解决办法:啥也不动,maven clean下,重启 1. Q2 layui控制下拉框高度 解决 .layui- ...

  3. sql下的xml配置文件中特殊使用的sql语句编写

    1.使用服用的sql语句------------查询学生表所有字段 <sql id="selectAllStuAll"> select stu.id,stu.name, ...

  4. Nginx环境下设置zblog伪静态方法

    Apache的环境非常简单.可以点击创建 .htaccess就可以了 Nginx环境下设置伪静态,并没有那个一键创建的按钮.只看到了这样的一个提示. 别的环境未测试.宝塔面板中 反正我是没找到. 宝塔 ...

  5. VS2017运行emwin模拟机不能运行的解决部分

    宇宙第一开发工具的功能太强大了,今天我们来介绍怎么解决VS2017的C++功能运行emwin模拟机不能运行的解决部分 编译软件:Visual Studio 2017:     emwin模拟机版本:S ...

  6. LCD应用程序测试

    #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl ...

  7. 搜索---BFS

    搜索   深度优先搜索和广度优先搜索广泛的应用于树和图中,但是他们的应用远不止于此. BFS   广度优先搜索一层一层地进行遍历,每层遍历都是以上一层遍历的结果作为起点,遍历一个距离能访问到的所有节点 ...

  8. <input>/<textarea>输入框设置默认提示文字(隐藏式)

    html代码如下: <tr>    <td>签   名:</td>    <td><input type="text" nam ...

  9. Spring基础学习笔记

    1. Spring入门 1. 1 Spring的体系结构 1.2 HelloWorld 1.2.1 Maven的使用 1)maven 的javase工程目录结构: 2)maven的settings.x ...

  10. C++ 编译器的安装(MinGW)

    GNU GNU是一个自由软件工程项目,GNU工程已经开发了一个被称为“GNU”(GNU是“不是UNIX”的缩写)的.对Unix向上兼容的完整的自由软件系统(free software system). ...