Java Thread系列(七)死锁
Java Thread系列(七)死锁
当线程需要同时持有多个锁时,有可能产生死锁。考虑如下情形:
线程 A 当前持有互斥所锁 lock1,线程 B 当前持有互斥锁 lock2。接下来,当线程 A 仍然持有 lock1 时,它试图获取 lock2,因为线程 B 正持有 lock2,因此线程 A 会阻塞等待线程 B 对 lock2 的释放。如果此时线程 B 在持有 lock2 的时候,也在试图获取 lock1,因为线程 A 正持有 lock1,因此线程 B 会阻塞等待 A 对 lock1 的释放。二者都在等待对方所持有锁的释放,而二者却又都没释放自己所持有的锁,这时二者便会一直阻塞下去。这种情形称为死锁。
下面给出一个两个线程间产生死锁的示例,如下:
/**
* 多个线程挣抢同一份资源,容易造成死锁
* @author: leigang
* @version: 2018-05-05
*/
public class DeadThread {
public static void main(String[] args) {
Object goods = new Object();
Object money = new Object();
new Test1(goods, money).start();
new Test2(goods, money).start();
}
static class Test1 extends Thread {
private Object goods;
private Object money;
public Test1(Object goods, Object money) {
this.goods = goods;
this.money = money;
}
@Override
public void run() {
while (true) {
test();
}
}
public void test() {
synchronized (goods) { // (1)
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (money) {
}
}
System.out.println(Thread.currentThread().getName() + "先交货再给钱");
}
}
static class Test2 extends Thread {
private Object goods;
private Object money;
public Test2(Object goods, Object money) {
this.goods = goods;
this.money = money;
}
@Override
public void run() {
while (true) {
test();
}
}
public void test() {
synchronized (money) { // (2)
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (goods) {
}
}
System.out.println(Thread.currentThread().getName() + "先给钱再交货");
}
}
}
说明:线程 1 持有 goods 锁并打算获取 money 锁,但线程 2 已经持有 money 锁并打算获取 goods 锁,由于这两个锁都被锁住,所以这两个线程都不能获取相应的锁,这样就产生了死锁。
大部分代码并不容易产生死锁,死锁可能在代码中隐藏相当长的时间,等待不常见的条件地发生,但即使是很小的概率,一旦发生,便可能造成毁灭性的破坏。避免死锁是一件困难的事,遵循以下原则有助于规避死锁:
1、只在必要的最短时间内持有锁,考虑使用同步语句块代替整个同步方法;
2、尽量编写不在同一时刻需要持有多个锁的代码,如果不可避免,则确保线程持有第二个锁的时间尽量短暂;
3、创建和使用一个大锁来代替若干小锁,并把这个锁用于互斥,而不是用作单个对象的对象级别锁;
既然多个线程操作同一个对象容易产生死锁,那么如何解决这个问题呢?一个经典的解决方案是 生产者-消费者模式
参考:
《Java 并发编程》:http://www.importnew.com/20638.html
每天用心记录一点点。内容也许不重要,但习惯很重要!
Java Thread系列(七)死锁的更多相关文章
- Java Thread系列(二)线程状态
Java Thread系列(二)线程状态 一.线程的五种状态 新建状态(New):新创建了一个线程对象,尚未启动. 就绪状态(Runnable):也叫可运行状态.线程对象创建后,其他线程调用了该对象的 ...
- Java Thread系列(十)生产者消费者模式
Java Thread系列(十)生产者消费者模式 生产者消费者问题(producer-consumer problem),是一个多线程同步问题的经典案例.该问题描述了两个共亨固定大小缓冲区的线程-即所 ...
- java多线程系列(七)---Callable、Future和FutureTask
Callable.Future和FutureTask 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量 ...
- Java Thread系列(四)线程通信
Java Thread系列(四)线程通信 一.传统通信 public static void main(String[] args) { //volatile实现两个线程间数据可见性 private ...
- Java Thread系列(五)synchronized
Java Thread系列(五)synchronized synchronized锁重入 关键字 synchronized 拥有锁重入的功能,也就是在使用 synchronized 时,当线程等到一个 ...
- Java Thread系列(三)线程安全
Java Thread系列(三)线程安全 一.什么是线程安全 线程安全概念:当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的. 线程安全来 ...
- Java Thread系列(一)线程创建
Java Thread系列(一)线程创建 Java 中创建线程主要有三种方式:继承 Thread.实现 Runnable 接口.使用 ExecutorService.Callable.Future 实 ...
- Java Thread系列(十)Future 模式
Java Thread系列(十)Future 模式 Future 模式适合在处理很耗时的业务逻辑时进行使用,可以有效的减少系统的响应时间,提高系统的吞吐量. 一.Future 模式核心思想 如下的请求 ...
- Java Thread系列(九)Master-Worker模式
Java Thread系列(九)Master-Worker模式 Master-Worker模式是常用的并行设计模式. 一.Master-Worker 模式核心思想 Master-Worker 系统由两 ...
随机推荐
- CH2101 可达性统计
题意 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 分析 有向无环图,可以按拓扑序逆序统计答案.可以用bitset维护可达性. 时间复杂度\(O(N ...
- 转-Vue.js2.0从入门到放弃---入门实例(一)
http://blog.csdn.net/u013182762/article/details/53021374 标签: Vue.jsVue.js 2.0Vue.js入门实例Vue.js 2.0教程 ...
- 每日一条 Git 命令:git merge remote master
每日一条 Git 命令:git merge remote master 当远程的分支更新后,需要将自己的代码与远程的分支合并就用以下这个命令合并. git merge remote master 如果 ...
- 02 - Unit08:搜索笔记功能、搜索分页、处理插入数据库乱码问题
搜索笔记功能 按键监听事件 $("#search_note").keydown(function(event){ var code=event.keyCode; if(code== ...
- C++ 内连接与外连接 (转)
啥叫内连接 外连接 我们知道编译的时候(假如编译器是VS),是以源文件cpp文件为单位,编译成一个个的obj文件,然后再通过链接器把不同的obj文件链接起来. 简单的说,如果一些变量或函数的定义是内连 ...
- python 下载图片的方法
a='http://wx1.sinaimg.cn/mw600/006HOayNgy1fqjdi2nxohj32pw3o8x6s.jpg' #图片下载地址 ( 这里改成 文件txt地址)w='/U ...
- native关键字(本地方法)、 java调用so动态链接库
Java native关键字 一. 什么是Native Method 简单地讲,一个Native Method就是一个java调用非java代码的接口.一个Native Method是这样一个ja ...
- zabbix触发器函数 count
转摘至梅总文章 一直没用过这个函数,今天研究了下,确实很有用(用过的忽略): 之前很多功能都是用max,min,avg曲线实现的,其实用count最合理(如典典刚用的高防持续N次ping超时). ...
- pyinstaller的使用方法 by 王大龙
---------------------------------------------------------------------------------------------------- ...
- ease,seae-in,ease-in-out,ease-out区别
值 描述 linear 规定以相同速度开始至结束的过渡效果(等于 cubic-bezier(0,0,1,1)).(匀速) ease 规定慢速开始,然后变快,然后慢速结束的过渡效果(cubic-bezi ...