首页 > 编程 > Java > 正文

Java多线程(6)——死锁

2019-11-06 07:48:04
字体:
来源:转载
供稿:网友

An example for dead lock:

package com.way.threads;public class DeadLock { public static void main(String[] args) throws InterruptedException{ Object obj1=new Object(); Object obj2=new Object(); Object obj3=new Object(); Thread t1=new Thread(new SyncThread(obj1,obj2),"thread1"); Thread t2=new Thread(new SyncThread(obj2,obj3),"thread2"); Thread t3=new Thread(new SyncThread(obj3,obj1),"thread3"); t1.start(); Thread.sleep(5000); t2.start(); Thread.sleep(5000); t3.start(); }}class SyncThread implements Runnable{ Object obj1; Object obj2; public SyncThread(Object obj1,Object obj2){ this.obj1=obj1; this.obj2=obj2; } public void run(){ String name=Thread.currentThread().getName(); System.out.PRintln(name+" begin to run"); synchronized(obj1){ System.out.println(name +" is using "+obj1); System.out.println(name+" want "+obj2); work(); synchronized (obj2) { System.out.println(name +" is using "+obj2); work(); } System.out.println(name +" release "+obj2); } System.out.println(name +" release "+obj1); System.out.println(name+" finish runing"); } public void work(){ try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } }}

Output:

thread1 begin to runthread1 is using java.lang.Object@1aeb83aethread1 want java.lang.Object@142c6e83thread2 begin to runthread2 is using java.lang.Object@142c6e83thread2 want java.lang.Object@22896964thread3 begin to runthread3 is using java.lang.Object@22896964thread3 want java.lang.Object@1aeb83ae

Obviously, threads have been locked by each other. This is Dead Lock.

什么是死锁? 如果一个进程集合里面的每个进程都在等待这个集合中的其他一个进程(包括自身)才能继续往下执行,若无外力他们将无法推进,这种情况就是死锁,处于死锁状态的进程称为死锁进程

产生死锁的四个必要条件: (1) 互斥条件:一个资源每次只能被一个进程使用。 (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。 (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

处理死锁的基本方法:

1.预防死锁:通过设置一些限制条件,去破坏产生死锁的必要条件 2.避免死锁:在资源分配过程中,使用某种方法避免系统进入不安全的状态,从而避免发生死锁 3.检测死锁:允许死锁的发生,但是通过系统的检测之后,采取一些措施,将死锁清除掉 4.解除死锁:该方法与检测死锁配合使用

具体措施:

避免嵌套封锁:这是死锁最主要的原因的,如果你已经有一个资源了就要避免封锁另一个资源。如果你运行时只有一个对象封锁,那是几乎不可能出现一个死锁局面的。例如,这里是另一个运行中没有嵌套封锁的run()方法,而且程序运行没有死锁局面,运行得很成功。

尽可能减少封锁对象的数量和封锁时间:只对想要运行的资源获取封锁,比如封锁对象的特定属性而不是整个对象。减少封锁时间:如果一个线程要取得某一资源并封锁后,尽快完成这个资源相关的操作并及时释放。

调整资源占有顺序:类如最经典的哲学家吃饭问题,所有人都先拿左筷子后拿右筷子,如果其中一个反过来,思索概率就会降低。

设置最长等待:如果两个线程正在等待对象结束,无限期的使用线程加入,如果你的线程必须要等待另一个线程的结束,若是等待进程的结束加入最好准备最长时间。在java.util.concurrent库中有相关支持

其他阅读资料: http://www.importnew.com/9668.html http://www.cnblogs.com/jijiji/p/4855581.html http://blog.csdn.net/defonds/article/details/44021605/#t77 http://ifeve.com/java-concurrency-thread-directory/ 《Java编程思想》


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表