A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李大伟 高级黑马   /  2013-6-3 11:21  /  1635 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 李大伟 于 2013-6-3 19:36 编辑

产生死锁的原因

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

7 个回复

倒序浏览
1.互斥条件,线程使用的资源至小有一个是不能共享的,一个线程只能一个人访问。
2.至小有一个进程他必须持有一个资源且正在等待获取一个当前被别的进程持有的资源,也就是说,要发生死锁,至少有一个线程必须执行并且等待下一个进程。
3.资源不能被进程抢占,所有的进程必须把资源释放当作普通事件。
4.必须有循环等待,这时,一个进程等待其他进程所持有的资源,后者有在等待另一个进程所持有的资源,这样一直下去,直到有个进程在等待第一个进程所持有的资源,使得大家都被锁住。

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报
有一组进程或线程,其中每个都在等待一个只有其他进程或线程才可以进行的操作,则称他们发生死锁。
也就是一旦有多个进程,且他们都要争用对多个所锁的独占访问,就可能发生死锁。
最常见的死锁形式就是:线程1持有对象a上的锁,而且等待对象b上的锁。
而线程2持有对象b上的锁,却在等待a的锁,
这两个进程都不会获得第二个锁,也不会释放第一个锁,所以他们就会一直等待下去。
这就是死锁产生的原因,其他复杂的死锁,也是这个原理

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报
产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报
原因在于:
被synchronized 修饰的函数a  和 被synchronized 修饰的函数b 持有不同的锁,却相互调用而导致的

举个例子:
  1. class Test implements Runnable
  2. {
  3.         private boolean flag;
  4.         Test(boolean flag){
  5.                 this.flag = flag;
  6.         }

  7.         public void run(){
  8.                 if (flag)
  9.                 {
  10.                         synchronized(MyLock.locka){
  11.                                 System.out.println("if locka");
  12.                                 synchronized(MyLock.lockb){
  13.                                         System.out.println("if lockb");
  14.                                 }
  15.                         }
  16.                 }else{
  17.                         synchronized(MyLock.lockb){
  18.                                 System.out.println("else lockb");
  19.                                 synchronized(MyLock.locka){
  20.                                         System.out.println("else locka");
  21.                                 }
  22.                         }
  23.                 }
  24.         }
  25. }

  26. class MyLock
  27. {
  28.         static Object locka = new Object();
  29.         static Object lockb = new Object();
  30. }

  31. class DeadLockTest
  32. {
  33.         public static void main(String[]args){
  34.                 Thread t1 = new Thread(new Test(true));
  35.                 Thread t2 = new Thread(new Test(false));
  36.                 t1.start();
  37.                 t2.start();
  38.         }
  39. }
复制代码
毕老师的视频在第十一天
回复 使用道具 举报
多线程同步为什么会产生死锁?

死锁产生原因:线程1锁住资源A等待资源B,线程2锁住B资源等待A资源,两个线程都在等待自己所需的资源,而这些资源被另外的线程锁住,这些线程你等我,我等你,谁也不愿意让出资源,造成死锁问题,程序停止运行。



举个现实生活中的例子理解死锁:

有两辆汽车,汽车1和汽车2,汽车1后备箱内装着汽车2启动需要的汽油,汽车2后背箱内装着汽车1启动所需的电瓶;但是汽油和电瓶都被锁住了,汽车1和汽车2的车主,都在等待对方打开后背箱的锁把自己所需要的资源给自己,就这样你等我,我等你,两辆汽车就在那停着谁走不了。


避免死锁问题出现的办法:

不要分别同步各个资源的操作代码块,而是统一放在一个同步块中

就是不要把汽油和电瓶分别锁起来,放在同一个箱子里用一把锁锁起来,两个车主都有这把锁的钥匙

死锁问题实例:
  1. 01./**  
  2. 02. * 多线程死锁问题  
  3. 03. */  
  4. 04.public class DeadLock implements Runnable  {  
  5. 05.  
  6. 06.   public boolean flag=true;  
  7. 07.   private static Object res1=new Object();   //资源1  
  8. 08.   private static Object res2=new Object();   //资源2  
  9. 09.     
  10. 10.    public void run() {  
  11. 11.      
  12. 12.          if(flag){  
  13. 13.               
  14. 14.              /*锁定资源res1*/  
  15. 15.              synchronized(res1){  
  16. 16.                  System.out.println("锁住资源1,等待资源2.。。。");  
  17. 17.                    
  18. 18.                  try {  
  19. 19.                    Thread.sleep(100);  
  20. 20.                } catch (InterruptedException e) {  
  21. 21.                     
  22. 22.                    e.printStackTrace();  
  23. 23.                }  
  24. 24.         
  25. 25.               /*锁定资源res 2*/  
  26. 26.               synchronized(res2){  
  27. 27.               
  28. 28.                  System.out.println("Complete.");  
  29. 29.                }  
  30. 30.              }  
  31. 31.            
  32. 32.        }else{  
  33. 33.              
  34. 34.            /*锁定资源2*/  
  35. 35.            synchronized(res2){  
  36. 36.                System.out.println("锁住资源2,等待资源1。。。。。");  
  37. 37.            }  
  38. 38.              
  39. 39.                    try {  
  40. 40.                        Thread.sleep(100);  
  41. 41.                    } catch (InterruptedException e) {  
  42. 42.                          
  43. 43.                        e.printStackTrace();  
  44. 44.                    }  
  45. 45.                    //锁定资源res1  
  46. 46.                     synchronized(res1){  
  47. 47.                         System.out.println("Complete.");  
  48. 48.                     }  
  49. 49.            }  
  50. 50.          }  
  51. 51.      
  52. 52.public static void main(String[] args) {  
  53. 53.         
  54. 54.         
  55. 55.    DeadLock r1=new DeadLock();   //创建线程对象  
  56. 56.    DeadLock r2=new DeadLock();  
  57. 57.      
  58. 58.    r2.flag=false;  
  59. 59.      
  60. 60.    Thread t1=new Thread(r1);  //创建线程  
  61. 61.    Thread t2=new Thread(r2);  
  62. 62.      
  63. 63.    t1.start();  
  64. 64.    t2.start();  
  65. 65.  
  66. 66.    }  
  67. 67.      
  68. 68.      
  69. 69.      
  70. 70.      
  71. 71.}  
复制代码
复制代码


点评

我觉得你这个说得好啊,呵呵  发表于 2013-6-3 19:36

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报 1 0
死锁其实开发中并不常用,大部分仅仅是为了应付面试!所以,
  1. public class DeadLock implements Runnable{

  2.         private boolean f ;
  3.         public DeadLock(boolean f){this.f = f;}
  4.         public void run() {
  5.                 while(true){
  6.                         //死循环,演示2个线程,一个线程中,的f是true 另一个线程的f是false
  7.                        
  8.                         if(f==true){
  9.                                 //第一个线程,判断f为true,使用LockA锁
  10.                                 synchronized(LockA.locka){
  11.                                         System.out.println("if...locka");//持有LockA锁
  12.                                         synchronized(LockB.lockb){
  13.                                                 System.out.println("if...lockb");
  14.                                         }
  15.                                 }
  16.                         }else{
  17.                                 //第二个线程,判断f为false
  18.                                 synchronized(LockB.lockb){
  19.                                         System.out.println("else..lockb");//持有LockB锁
  20.                                         synchronized(LockA.locka){
  21.                                                 System.out.println("else..locka");
  22.                                         }
  23.                                 }
  24.                         }
  25.                 }
  26.         }
  27.        
  28. }

  29. /*
  30. * 造2个锁
  31. */
  32. class LockA{
  33.         public static LockA locka = new LockA();
  34. }
  35. class LockB{
  36.         public static LockB lockb = new LockB();
  37. }

  38. public class DeadTest {

  39.         /*
  40.          * 测试死锁程序
  41.          */
  42.         public static void main(String[] args) {
  43.                 DeadLock d1 = new DeadLock(true);
  44.                 DeadLock d2 = new DeadLock(false);
  45.                
  46.                 Thread t1 = new Thread(d1);
  47.                 Thread t2 = new Thread(d2);
  48.                
  49.                 t1.start();
  50.                 t2.start();
  51.         }

  52. }
复制代码
差不多的理解,然后把代码记熟悉了就好!

死锁.JPG (46.32 KB, 下载次数: 1)

死锁.JPG
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马