一、死锁是什么?

举个例子:两个人一起吃饭,每个人都拿了一只筷子,双方都在等待对方将筷子让给自己,结果两个人都吃不了饭。这种情况和计算机中的死锁情况很相似。

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

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

  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的接口对象,但是不影响结果;和第二个相比,第一个方法排除了不确定因素,是验证死锁程序的有效方法。

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

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

    java多线程之线程死锁 产生死锁的主要原因: 由于系统资源不足. 进程执行推进的顺序不合适. 资源分配不当等. 假设系统资源充足.进程的资源请求都可以得到满足,死锁出现的可能性就非常低.否则就会因争 ...

  2. Java多线程——线程的死锁

    Java多线程——线程的死锁 摘要:本文主要介绍了Java多线程中遇到的死锁问题. 部分内容来自以下博客: https://www.cnblogs.com/wy697495/p/9757982.htm ...

  3. Java多线程中的死锁

    Java多线程中的死锁 死锁产生的原因 线程死锁是指由两个以上的线程互相持有对方所需要的资源,导致线程处于等待状态,无法往前执行. 当线程进入对象的synchronized代码块时,便占有了资源,直到 ...

  4. Java多线程中的死锁问题

    Java程序基本都要涉及到多线程,而在多线程环境中不可避免的要遇到线程死锁的问题.Java不像数据库那么能够检测到死锁,然后进行处理,Java中的死锁问题,只能通过程序员自己写代码时避免引入死锁的可能 ...

  5. java多线程(八)-死锁问题和java多线程总结

    为了防止对共享受限资源的争夺,我们可以通过synchronized等方式来加锁,这个时候该线程就处于阻塞状态,设想这样一种情况,线程A等着线程B完成后才能执行,而线程B又等着线程C,而线程C又等着线程 ...

  6. java 多线程争抢资源死锁

    多线程争抢资源死锁的原理就是,A线程正在持有锁1却想获取锁2,B线程正在持有锁2却要获取锁1 代码如下: public class Main { static ReentrantLock lock1 ...

  7. java多线程中的死锁情况读书笔记

    多线程中的死锁 在前面的分析中,我们知道一个对象可以用Synchronized方法或者其他的加锁形式来防止别的任务在互斥还没有释放的时候就访问这个对象. 试想一下这样的情况:某个任务在等待另一个任务, ...

  8. Java多线程7:死锁

    前言 死锁单独写一篇文章是因为这是一个很严重的.必须要引起重视的问题.这不是夸大死锁的风险,尽管锁被持有的时间通常很短,但是作为商业产品的应用程序每天可能要执行数十亿次获取锁->释放锁的操作,只 ...

  9. Java多线程---------同步与死锁:synchronized;等待与唤醒:wait、notify、notifyAll;生命周期

    1.问题的引出 class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ ...

  10. java多线程13 : 死锁

    前言 死锁单独写一篇文章是因为这是一个很严重的.必须要引起重视的问题.这不是夸大死锁的风险,尽管锁被持有的时间通常很短,但是作为商业产品的应用程序每天可能要执行数十亿次获取锁->释放锁的操作,只 ...

随机推荐

  1. php中发送email

    一.使用PHP内置的mail()函数 看了一下手册,就直接开始写代码了,如下 <?php $to = "test@163.com"; //收件人 $subject = &qu ...

  2. (转载)XML解析之-XStream解析

    转载来源:http://hwy584624785.iteye.com/blog/1168680 本例使用XStream生成一个xml文件,再发序列化xml文件内容. XStream是一个简单的类库,可 ...

  3. Mac之vim普通命令使用[转]

    高级一些的编辑器,都会包含宏功能,vim当然不能缺少了,在vim中使用宏是非常方便的: :qx     开始记录宏,并将结果存入寄存器xq     退出记录模式@x     播放记录在x寄存器中的宏命 ...

  4. BZOJ 1485: [HNOI2009]有趣的数列

    Description 求长度为 \(2n\) 的序列.要求 1. \(a_1<a_3<a_5<...<a_{2n-1}\) . 2. \(a_2<a_4<a_6& ...

  5. Linux nohup 程序后台运行

    &方式: Unix/Linux下一般想让某个程序在后台运行,很多都是使用 & 在程序结尾来让程序自动运行.比如我们要运行mysql在后台:          /usr/local/my ...

  6. 音频DAC剖析---解开HI-FI音质的秘密

    选自:http://mp3.zol.com.cn/54/547689.html 无论我们是买MP3.MP4也好,实际上我们的数码播放器最经常使用的就是音乐播放功能,所以数码播放器的音质,一直是消费者的 ...

  7. 转:SQL子句的执行顺序

    SQL 不同于与其他编程语言的最明显特征是处理代码的顺序.在大数编程语言中,代码按编码顺序被处理,但是在SQL语言中,第一个被处理的子句是FROM子句,尽管SELECT语句第一个出现,但是几乎总是最后 ...

  8. .net MVC借助Iframe实现无刷新上传文件

    html: <div id="uploadwindow" style="display: none;"> <form action=" ...

  9. win7桌面背景地址

    C:\Users\你的用户名\AppData\Local\Microsoft\Windows\Themes\Alaskan L\DesktopBackground

  10. js隐藏div和class

    <style type="text/css"> //div用点//class# .footer {  display:none;  } #footer {  displ ...