转:【Java并发编程】之九:死锁(含代码)
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17200937
当线程需要同时持有多个锁时,有可能产生死锁。考虑如下情形:
线程A当前持有互斥所锁lock1,线程B当前持有互斥锁lock2。接下来,当线程A仍然持有lock1时,它试图获取lock2,因为线程B正持有lock2,因此线程A会阻塞等待线程B对lock2的释放。如果此时线程B在持有lock2的时候,也在试图获取lock1,因为线程A正持有lock1,因此线程B会阻塞等待A对lock1的释放。二者都在等待对方所持有锁的释放,而二者却又都没释放自己所持有的锁,这时二者便会一直阻塞下去。这种情形称为死锁。
下面给出一个两个线程间产生死锁的示例,如下:
- public class Deadlock extends Object {
- private String objID;
- public Deadlock(String id) {
- objID = id;
- }
- public synchronized void checkOther(Deadlock other) {
- print("entering checkOther()");
- try { Thread.sleep(2000); }
- catch ( InterruptedException x ) { }
- print("in checkOther() - about to " + "invoke 'other.action()'");
- //调用other对象的action方法,由于该方法是同步方法,因此会试图获取other对象的对象锁
- other.action();
- print("leaving checkOther()");
- }
- public synchronized void action() {
- print("entering action()");
- try { Thread.sleep(500); }
- catch ( InterruptedException x ) { }
- print("leaving action()");
- }
- public void print(String msg) {
- threadPrint("objID=" + objID + " - " + msg);
- }
- public static void threadPrint(String msg) {
- String threadName = Thread.currentThread().getName();
- System.out.println(threadName + ": " + msg);
- }
- public static void main(String[] args) {
- final Deadlock obj1 = new Deadlock("obj1");
- final Deadlock obj2 = new Deadlock("obj2");
- Runnable runA = new Runnable() {
- public void run() {
- obj1.checkOther(obj2);
- }
- };
- Thread threadA = new Thread(runA, "threadA");
- threadA.start();
- try { Thread.sleep(200); }
- catch ( InterruptedException x ) { }
- Runnable runB = new Runnable() {
- public void run() {
- obj2.checkOther(obj1);
- }
- };
- Thread threadB = new Thread(runB, "threadB");
- threadB.start();
- try { Thread.sleep(5000); }
- catch ( InterruptedException x ) { }
- threadPrint("finished sleeping");
- threadPrint("about to interrupt() threadA");
- threadA.interrupt();
- try { Thread.sleep(1000); }
- catch ( InterruptedException x ) { }
- threadPrint("about to interrupt() threadB");
- threadB.interrupt();
- try { Thread.sleep(1000); }
- catch ( InterruptedException x ) { }
- threadPrint("did that break the deadlock?");
- }
- }
运行结果如下:
从结果中可以看出,在执行到other.action()时,由于两个线程都在试图获取对方的锁,但对方都没有释放自己的锁,因而便产生了死锁,在主线程中试图中断两个线程,但都无果。
大部分代码并不容易产生死锁,死锁可能在代码中隐藏相当长的时间,等待不常见的条件地发生,但即使是很小的概率,一旦发生,便可能造成毁灭性的破坏。避免死锁是一件困难的事,遵循以下原则有助于规避死锁:
1、只在必要的最短时间内持有锁,考虑使用同步语句块代替整个同步方法;
2、尽量编写不在同一时刻需要持有多个锁的代码,如果不可避免,则确保线程持有第二个锁的时间尽量短暂;
3、创建和使用一个大锁来代替若干小锁,并把这个锁用于互斥,而不是用作单个对象的对象级别锁;
转:【Java并发编程】之九:死锁(含代码)的更多相关文章
- java并发编程如何预防死锁
在java并发编程领域已经有技术大咖总结出了发生死锁的条件,只有四个条件都发生时才会出现死锁: 1.互斥,共享资源X和Y只能被一个线程占用 2.占有且等待,线程T1已经取得共享资源X,在等待共享资源Y ...
- Java并发编程实战 04死锁了怎么办?
Java并发编程文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 前提 在第三篇 ...
- java并发编程(九)死锁
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17200937 大部分代码并不容易产生死锁,死锁可能在代码中隐藏相当长的时间,等待不常见的条 ...
- Java并发编程(九):拓展
java多线程死锁理解 Java多线程并发最佳实践 Spring与线程安全 HashMap与ConcurrentHashMap 关于java集合类HashMap的理解 , 数据结构之 ...
- Java并发编程(九)安全发布
之前讨论是如何将对象封闭在线程之中,这样可以减少一些并发带来的同步和可见性问题.但是在有些时候,我们希望在多个线程间共享对象,此时必须确保安全地进行共享. [不安全发布的示例] 可见性问题:其他线程看 ...
- Java并发编程(九)-- 进程饥饿和公平锁
上一章已经提到“如果一个进程被多次回滚,迟迟不能占用必需的系统资源,可能会导致进程饥饿”,本文我们详细的介绍一下“饥饿”和“公平”. Java中导致饥饿的原因 在Java中,下面三个常见的原因会导致线 ...
- Java并发编程(九)并发容器
并发容器的简单介绍: ConcurrentHashMap代替同步的Map(Collections.synchronized(new HashMap())),众所周知,HashMap是根据散列值分段存储 ...
- 【Java并发编程】:死锁
当线程需要同时持有多个锁时,有可能产生死锁.考虑如下情形: 线程A当前持有互斥所锁lock1,线程B当前持有互斥锁lock2.接下来,当线程A仍然持有lock1时,它试图获取lock2,因为线程B正持 ...
- Java并发编程(九)线程间协作(下)
上篇我们讲了使用wait()和notify()使线程间实现合作,这种方式很直接也很灵活,但是使用之前需要获取对象的锁,notify()调用的次数如果小于等待线程的数量就会导致有的线程会一直等待下去.这 ...
- java并发编程(九)----(JUC)CyclicBarrier
上一篇我们介绍了CountDownlatch,我们知道CountDownlatch是"在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待",即CountDownL ...
随机推荐
- Open-Falcon第七步安装报警模块(小米开源互联网企业级监控系统)
sender调用各个公司提供的mail-provider和sms-provider,按照某个并发度,从redis中读取邮件.短信并发送,alarm生成的报警短信和报警邮件都是直接写入redis即可,s ...
- iframe中的模态框遮罩父窗口原理
关键点: css的position定位为fixed或absolute css的z-index, 最顶层的值最大如遮罩层为0那么弹出框最好是大于等于1的整数,总之记住弹出层要比遮罩的z-index值大就 ...
- 移动端https抓包那些事--进阶篇
上一次和大家介绍了手机端https抓包的初级篇,即在手机未root或者未越狱的情况下如何抓取https流量,但是当时分析应用时会发现,好多应用的https的流量还是无法抓取到,这是为什么呢? 主要原因 ...
- /etc/shadow,/etc/passwd,/etc/shadow,/etc/passwd文件的内容解释
1.1 /etc/passwd文件内容格式 该目录存储的是操作系统用户信息,该文件为所有用户可见 用户名: 密码 : uid : gid :用户描述:主目录:登陆shell 举个 ...
- 关于MFC实时的视频处理
最近老师,让我做一下关于视频处理方面的一个项目,在实时处理这里实在是卡住了太长时间,因为不知道如何使用多线程来进行实时检测,终于有点眉目,来写个笔记记录一下. 首先需要介绍一下关于项目的背景,做一个人 ...
- php中自动加载类_autoload()和spl_autoload_register()实例详解
一._autoload 自动加载类:当我们实例化一个未定义的类时,就会触此函数.到了php7.1以后版本不支持此函数好像抛弃了 新建一个类文件名字自己随便去:news类在auto.php文件里面去实例 ...
- android学习笔记之GridView的使用
除了listview会使用适配器外,还有一种就是GridView,listview是单列多行的显示形式,适用于多项目的查看.而GridView是多行多列的显示形式,一般用在查看图片样式的activit ...
- Eclipse 安装插件(aptana、svn 、git、Java EE、JSHint)
转发9 1.安装 aptana 插件: * 依次点击:Help -> Install New Software... -> Add * 输入:http://download.aptan ...
- jquery插件封装
HTML <!DOCTYPE html> <html> <head> <title></title> <style> .page ...
- Netty SSL安全配置
Netty SSL安全配置 [TOC] 摘要 在研发蜂鸟部署平台的过程中,涉及到平台网关和前置agent的通信加密,虽然目前软件在内网中,但是由于蜂鸟平台和agent的特殊性,一旦被控制,部署的软件就 ...