【JAVA多线程问题之死锁】

一、死锁是什么?

举个例子:两个人一起吃饭,每个人都拿了一只筷子,双方都在等待对方将筷子让给自己,结果两个人都吃不了饭。这时候死锁就形成了。

假设有两个线程,互相等待对方释放占有的锁,但是释放锁的条件又不可能形成,这时候死锁就形成了。

还是买票的问题,有的时候时会发生死锁的,将以前的代码改动一下,将会产生死锁:

 1 /*
 2 死锁的产生
 3 */
 4 class Ticket implements Runnable
 5 {
 6     Object obj=new Object();
 7     boolean flag;
 8     private int sum=1000;
 9     public void run()
10     {
11             if(flag==true)
12             {
13                 while(true)
14                 {
15                     synchronized(obj)
16                     {
17                         //->Thread1
18                         show();
19                     }
20                 }
21             }
22             else
23             {
24                 while(true)
25                 show();
26             }
27     }
28     public synchronized void show()
29     {
30         //->Thread0
31         synchronized(obj)
32         {
33             if(sum>0)
34             {
35                 try
36                 {
37                     Thread.sleep(10);
38                 }
39                 catch (InterruptedException e)
40                 {
41                 }
42                 System.out.println(Thread.currentThread().getName()+":function--"+sum--);
43             }
44         }
45     }
46 }
47 public class Demo
48 {
49     public static void main(String args[])
50     {
51         Ticket t=new Ticket();
52         t.flag=false;
53         Thread t1=new Thread(t);
54         Thread t2=new Thread(t);
55         t1.start();
56
57         try//加入等待时间,让线程0启动
58         {
59             Thread.sleep(10);
60         }
61         catch (InterruptedException e)
62         {
63
64         }
65         t.flag=true;
66         t2.start();
67     }
68 }

死锁的现象:

如图所示,光标停在下一行不断闪烁,没有任何输出。

死锁具体是怎么形成的?以上面的输出为例:

线程0启动之后,由于标志变量为false,所以走的是else块,进入死循环,调用show方法,拿到this锁,然后继续拿到obj锁,顺利执行完毕之后,依次释放obj锁、this锁,然后开始进行第二次循环,拿到了this锁,但是将要拿到obj锁的时候,CPU切换到了线程1,线程1启动之后,由于flag已经是true,所以走的是if块,拿到了obj锁,刚要拿this锁,CPU切换到了线程0,线程0已经拿到了this锁,所以开始请求obj锁,但是obj锁在线程1手里,所以CPU切换到了线程1;线程1已经拿到了obj锁,所以它开始请求this锁,但是this锁在线程0手里,于是CPU切换到了线程0;..................

我们经过上面的分析,由于两个线程手里各自拿着对方的锁,相互请求但是没有让其中一方先释放锁的条件,所以CPU在两个线程之间不断切换,但是不会执行任何一方的任务。

总结死锁产生的条件:

1.有两个或者两个以上的锁。

2.同步嵌套(锁的嵌套)

死锁代码简单实例1:

 1 class Demo implements Runnable
 2 {
 3     boolean flag;
 4     public Demo(){}
 5     public Demo(boolean flag)
 6     {
 7         this.flag=flag;
 8     }
 9     public void run()
10     {
11         if(flag)
12         {
13             while(true)
14             {
15                 synchronized(Sour.lock1)
16                 {
17                     System.out.println("if---------lock1-------");
18                     synchronized(Sour.lock2)
19                     {
20                         System.out.println("if-------lock2------");
21                     }
22                 }
23             }
24         }
25         else
26         {
27             while(true)
28             {
29                 synchronized(Sour.lock2)
30                 {
31                     System.out.println("else---------lock2-------");
32                     synchronized(Sour.lock1)
33                     {
34                         System.out.println("else-------lock1------");
35                     }
36                 }
37             }
38         }
39     }
40 }
41 class Sour
42 {
43     public static final  Object lock1=new Object();
44     public static final  Object lock2=new Object();
45 }
46 public class DeadLockDemo
47 {
48     public static void main(String args[])
49     {
50         Demo d1=new Demo(true);
51         Demo d2=new Demo(false);
52         Thread t1=new Thread(d1);
53         Thread t2=new Thread(d2);
54         t1.start();
55         t2.start();
56     }
57 }

死锁代码简单实例二:

 1 class Demo implements Runnable
 2 {
 3     boolean flag;
 4     public Demo(){}
 5     public Demo(boolean flag)
 6     {
 7         this.flag=flag;
 8     }
 9     public void run()
10     {
11         if(flag)
12         {
13             while(true)
14             {
15                 synchronized(Sour.lock1)
16                 {
17                     System.out.println("if---------lock1-------");
18                     synchronized(Sour.lock2)
19                     {
20                         System.out.println("if-------lock2------");
21                     }
22                 }
23             }
24         }
25         else
26         {
27             while(true)
28             {
29                 synchronized(Sour.lock2)
30                 {
31                     System.out.println("else---------lock2-------");
32                     synchronized(Sour.lock1)
33                     {
34                         System.out.println("else-------lock1------");
35                     }
36                 }
37             }
38         }
39     }
40 }
41 class Sour
42 {
43     public static final  Object lock1=new Object();
44     public static final  Object lock2=new Object();
45 }
46 public class DeadLockDemo
47 {
48     public static void main(String args[])
49     {
50         Demo d1=new Demo();
51         d1.flag=false;
52         //Demo d2=new Demo(false);
53         Thread t1=new Thread(d1);
54         Thread t2=new Thread(d1);
55
56         t1.start();
57         try
58         {
59             Thread.sleep(10);
60         }
61         catch (InterruptedException e)
62         {
63         }
64         d1.flag=true;
65         t2.start();
66     }
67 }

可以观察发现两个代码基本相同,只是主函数中的方法略有不同,其中,第一个代码有99.9%的几率在第三行就锁上;第二个代码要到几百行才能锁上,甚至有时候锁不上。

第一种方法创建了两个实现了Runnable的接口对象,但是不影响结果;和第二个相比,第一个方法排除了不确定因素,是验证死锁程序的有效方法。

时间: 2024-08-17 18:09:23

【JAVA多线程问题之死锁】的相关文章

java多线程之 ---- 线程死锁

java多线程之线程死锁 产生死锁的主要原因: 因为系统资源不足. 进程运行推进的顺序不合适. 资源分配不当等. 如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁.其次, 进程运行推进顺序与速度不同,也可能产生死锁. 产生死锁的四个必要条件:  互斥条件:一个资源每次只能被一个进程使用. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放. 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺. 循环等待条件:若干进

Java多线程中的死锁问题[转]

//申明:本文转载自http://www.cnblogs.com/digdeep/p/4448148.html <Java多线程中的死锁问题> Java程序基本都要涉及到多线程,而在多线程环境中不可避免的要遇到线程死锁的问题.Java不像数据库那么能够检测到死锁,然后进行处理,Java中的死锁问题,只能通过程序员自己写代码时避免引入死锁的可能性来解决. 1. Java中导致死锁的原因 Java中死锁最简单的情况是,一个线程T1持有锁L1并且申请获得锁L2,而另一个线程T2持有锁L2并且申请获得

java基础知识回顾之java Thread类学习(七)--java多线程安全问题(死锁)

死锁:是两个或者两个以上的线程被无限的阻塞,线程之间互相等待所需资源. 线程死锁产生的条件: 当两个线程相互调用Join()方法. 当两个线程使用嵌套的同步代码块的时候,一个线程占用了另一个线程的锁,互相等待阻塞,就有可能产生死锁. 下面看代码: 代码1:死锁的案例 package com.lp.ecjtu.Thread; /* 死锁:常见情景之一:同步的嵌套. */ class Ticket implements Runnable { private int num = 100; Object

Java多线程中的死锁问题

Java程序基本都要涉及到多线程,而在多线程环境中不可避免的要遇到线程死锁的问题.Java不像数据库那么能够检测到死锁,然后进行处理,Java中的死锁问题,只能通过程序员自己写代码时避免引入死锁的可能性来解决. 1. Java中导致死锁的原因 Java中死锁最简单的情况是,一个线程T1持有锁L1并且申请获得锁L2,而另一个线程T2持有锁L2并且申请获得锁L1,因为默认的锁申请操作都是阻塞的,所以线程T1和T2永远被阻塞了.导致了死锁.这是最容易理解也是最简单的死锁的形式.但是实际环境中的死锁往往

Java多线程7:死锁

前言 死锁单独写一篇文章是因为这是一个很严重的.必须要引起重视的问题.这不是夸大死锁的风险,尽管锁被持有的时间通常很短,但是作为商业产品的应用程序每天可能要执行数十亿次获取锁->释放锁的操作,只要在这数十亿次操作中只要有一次发生了错误,就可能导致程序中发生死锁,并且即使通过压力测试也不可能找出所有潜在的死锁. 死锁 一个经典的多线程问题. 当一个线程永远地持有一个锁,并且其他线程都尝试去获得这个锁时,那么它们将永远被阻塞,这个我们都知道.如果线程A持有锁L并且想获得锁M,线程B持有锁M并且想获得

java多线程13 : 死锁

前言 死锁单独写一篇文章是因为这是一个很严重的.必须要引起重视的问题.这不是夸大死锁的风险,尽管锁被持有的时间通常很短,但是作为商业产品的应用程序每天可能要执行数十亿次获取锁->释放锁的操作,只要在这数十亿次操作中只要有一次发生了错误,就可能导致程序中发生死锁,并且即使通过压力测试也不可能找出所有潜在的死锁. 死锁 一个经典的多线程问题. 当一个线程永远地持有一个锁,并且其他线程都尝试去获得这个锁时,那么它们将永远被阻塞,这个我们都知道.如果线程A持有锁L并且想获得锁M,线程B持有锁M并且想获得

Java多线程与并发——死锁与中断线程

过多的同步有可能出现死锁,死锁的操作一般是在程序运行的时候才有可能出现. 多线程中要进行资源的共享,就需要同步,但同步过多,就可能造成死锁. 死锁例子: package com.vince; /** * 线程死锁 * @author acer * */ public class DeadThreadDemo { public static void main(String[] args) { new DeadThread(); } } //顾客 class Customer{ public sy

java多线程中的死锁

产生死锁的原因:多个线程用到了多个锁,多个锁之间存在交叉关系,就有可能产生死锁. 下面是简单的死锁,下面代码中的死锁不是一定会产生. package demo_1; public class TestDeadLock { public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); Thread t1 = new Thread(thread1);

java多线程问题中死锁的一个实现

1.直接上代码: class LockDemo{ public static final Object A_LOCK=new Object(); public static final Object B_LOCK=new Object(); } public class ThreadLockDemo implements Runnable{ public boolean flag; public ThreadLockDemo(boolean flag) { this.flag=flag; } p