题记:写这篇博客要主是加深自己对死锁线程的认识和总结实现算法时的一些验经和训教,如果有错误请指出,万分感谢。

今天搞了一下Java的死锁机制,感到自己还是不怎么懂,所以就从一些简略的源代码中琢磨:我先尝试写了一个很简略的死锁代码:思绪是线程A取得B的锁但还没有取得C的锁,所以在等待取得C的锁,还线程A1取得了C的锁但没有取得B锁所以就在等待B的锁,所以就造成了相互等待,程序陷入死锁状态……

死锁程序:

public class DeadLock{
public static void main(String[] args) { 
     final Object a=new Object(),b=new Object();
    Thread t1 = new Thread(new A(a,b));
    Thread t2 = new Thread(new A1(a,b));
     t1.start();
    t2.start();
}
}
class  A implements Runnable{
    private  Object B,C;
    public A(Object B,Object C){
    this.B=B;
    this.C=C;
    }
@Override
public void run() { 
synchronized(B){ //取得B的锁
 System.out.println("A线程取得B的锁等待C的锁");
 synchronized(C){
 System.out.println("A线程取得B的锁也取得了C的锁");
 }
 }
}
}
class  A1 implements Runnable{
    private  Object B,C;
    public A1(Object B,Object C){
    this.B=B;
    this.C=C;
    }
@Override
public void run() {
 synchronized(C){ //取得B的锁
 System.out.println("A1线程取得B的锁等待C的锁");
 synchronized(B){
 System.out.println("A1线程取得B的锁也取得了C的锁");
 }
 }
}
}

线程A和A1处于相互等待对方释放锁,就这样一直对峙着,这段代码要避免死锁有两个方法:

方法一:在启动两个线程之间加入sleep()方法,只要休眠充足长的时光,让线程A先执行完再启动线程A1就可以避免死锁

t1.start();

try{

TimeUnit.SECONDS.sleep(5);

}catch(InterruptedException e){}
    t2.start();

方法二,采用join()方法

t1.start();t1.join();
    t2.start();t2.join();

在死锁案例中,最经典的课本案例应该是哲学家吃饭问题(我自己这样称谓),讲的是有5个哲学家,每个都做同样的事,一天的时光都在思考、吃饭的循环中渡过,饭桌上一共只有5只筷子,一个人必须要有两只筷子才能够吃饭,所以哲学家就必须向身旁的人拿筷子,当一同拿时就会发生死锁,假设哲学家都是先拿左边的筷子再拿右边的筷子,哲学家围成一圈,这样每个人左边和右边都有一只筷子。

例程:

package thread.test;
import java.util.concurrent.TimeUnit; 
public class DeadLock{
      public static void main(String[] args) { 
          try{

//一共有5双筷子5个哲学家
               Chopsticks[] chops=new Chopsticks[5];
               Philosopher[] peps=new Philosopher[5];  
               for(int i=0;i<5;i++){
                    chops[i] = new Chopsticks(i);
                 }
                 for(int i=0;i<5;i++){
                       peps[i] = new Philosopher(chops[i],chops[(i+1)/5],i);
                 }
                //启动五个线程
                 for(int i=0;i<5;i++){
                         new Thread(peps[i]).start();
                 }

    每日一道理
如果只看到太阳的黑点,那你的生活将缺少温暖;如果你只看到月亮的阴影,那么你的生命历程将难以找到光明;如果你总是发现朋友的缺点,你么你的人生旅程将难以找到知音;同样,如果你总希望自己完美无缺,假设你的这一愿望真的能如愿以偿,那么你最大的缺点就是没有缺点。

TimeUnit.SECONDS.sleep(4);//延时充足长的时光视察哲学家的动态

System.exit(0);  //程序必须退出!

}catch(InterruptedException e){

System.out.println("interrupted");

}   
         }
}
class Chopsticks { 
        private final int id;
        public Chopsticks(int i){
             id=i;
        }
        private boolean OnTake=false;
        synchronized public void take()throws InterruptedException{
             while(OnTake)
                    wait();
            OnTake=true;
       }
       synchronized public void drop(){
            OnTake=false;
             notifyAll();
       }
       public String toString(){
       return "chopstcks:"+id;
       }
}
class Philosopher implements Runnable{

private Chopsticks left;
         private Chopsticks right;
         private final int id;
         public Philosopher(Chopsticks l,Chopsticks r,int id){
         left = l;     //左边的筷子
         right = r;    //右边的筷子
         this.id=id; 
         }
        //模拟哲学家思考所占有的时光
        private void pause()throws InterruptedException{ 
                 TimeUnit.MILLISECONDS.sleep(400);
          }
        @Override
        public void run() {
        try{
           while(!Thread.interrupted()){
                   System.out.println(this+"在思考");
         pause();
         System.out.println(this+"拿筷子吃饭");
         left.take();   //先拿左边的筷子
         pause();
         right.take();   //这顿饭永久也吃不完
         System.out.println(this+"吃完放下筷子");
         left.drop();
         right.drop();
     }
     }catch(InterruptedException e){
          e.printStackTrace();
     }
   }
   public String toString(){
         return " 哲学家"+id;
    }

}
这段程序按照我们预想的结果是每个哲学家都在思考,然后顺次吃完饭后放下筷子让另外的人吃,因为每个人需要两根筷子,总有人会没有筷子!但实际情况是:每个人都先拿起左边的筷子,然后等待某一个人把右边的筷子给他,但每个人都是这样想的,所以每个人都拿不到对方的筷子,所以这顿饭永久也吃不完!程序陷入了死锁。话说到这里,我们就有须要晓得满足死锁的四个须要条件:1:互斥条件:资源每次只能被一个线程使用。如前面的“线程同步代码段”。 2:请求与坚持条件:一个线程因请求资源而阻塞时,对已取得的资源坚持不放。 3:不褫夺条件:进程已取得的资源,在未使用完之前,无法强行褫夺。 4:循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

这四个条件只要一个不满足就不会陷入死锁,一般我们容易破坏第四个条件,只要让其中一个哲学家先拿右边的筷子程序就不会陷入死锁!

修改后不会陷入死锁的程序:

for(int i=0;i<4;i++){
 peps[i] = new Philosopher(chops[i],chops[i+1],i);
 }
 //最后一个哲学家先拿右边的筷子,即chops[0]筷子
 peps[4] = new Philosopher(chops[0],chops[4],4);

看完这篇文章就留下了一个我从书上摘抄上去的练习:修改程序,使切当哲学家用完筷子以后,把筷子放在一个筷笼中,当哲学家要就餐时就从筷笼里取出下两根可用的筷子。这消除了死锁的可能吗?你能通过仅仅增加可用的筷子数目就从新引入死锁吗?如果要索要谜底,就请留下邮箱地址,我发谜底给你,或许你的谜底比我的好得多!交流是一种快乐!

文章结束给大家分享下程序员的一些笑话语录:

火车
一个年轻的程序员和一个项目经理登上了一列在山里行驶的火车,他们发现 列车上几乎都坐满了,只有两个在一起的空位,这个空位的对面是一个老奶 奶和一个年轻漂亮的姑娘。两个上前坐了下来。程序员和那个姑娘他们比较 暧昧地相互看对方。这时,火车进入山洞,车厢里一片漆黑。此时,只听见 一个亲嘴的声音,随后就听到一个响亮的巴掌声。很快火车出了山洞,他们 四个人都不说话。
那个老奶奶在喃喃道, “这个年轻小伙怎么这么无礼, 不过我很高兴我的孙女 扇了一个巴掌”。
项目经理在想,“没想到这个程序员居然这么大胆,敢去亲那姑娘,只可惜那 姑娘打错了人,居然给打了我。”
漂亮的姑娘想,“他亲了我真好,希望我的祖母没有打疼他”。
程序员坐在那里露出了笑容, “生活真好啊。 这一辈子能有几次机会可以在亲 一个美女的同时打项目经理一巴掌啊”

---------------------------------
原创文章 By
死锁和线程
---------------------------------

死锁线程探讨Java中的死锁现象的更多相关文章

  1. java中的死锁现象

    死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不可能正常终止. java 死锁产生的四个必要条件: 1.互斥使用,即当资源被一个线 ...

  2. 编写 Java 程序时, 如何在 Java 中创建死锁并修复它?

    经典但核心Java面试问题之一.如果你没有参与过多线程并发 Java 应用程序的编码,你可能会失败.

  3. 线程:Java中wait、notify、notifyAll使用详解

    基础知识 首先我们需要知道,这几个都是Object对象的方法.换言之,Java中所有的对象都有这些方法. public final native void notify(); public final ...

  4. 深入探讨Java中的异常与错误处理

    Java中的异常处理机制已经比较成熟,我们的Java程序到处充满了异常的可能,如果对这些异常不做预先的处理,那么将来程序崩溃就无从调试,很难找到异常所在的位置.本文将探讨一下Java中异常与错误的处理 ...

  5. Java中的死锁问题

    死锁问题: 例如有两个线程, 线程1与线程2. 线程1在执行的过程中, 要锁定对象1, 2才能完成整个操作, 首先锁定对象1, 再锁定对象2. 线程2在执行的过程中, 要锁定对象2, 1才能完成整个操 ...

  6. 转自CSDN-详述 Java 中的别名现象

    在任何编程语言中,赋值操作都是最常见的操作之一,Java 自然也不例外.赋值时,使用赋值操作符=,它的意思是:“将等号右边的值(右值),复制给左边的值(左值)”.右值可以是任何常数.变量或者表达式(只 ...

  7. 探讨 java中 接口和对象的关系

    接口是对象么?接口可以有对象么?这个问题要跟类比对着,或许更好理解;类是对象的模版.接口不是类,所以:接口肯定不是对象的模版.那接口跟对象有什么样的关系?还是得从类入手;因为类实现了接口,所以可以说, ...

  8. Java中的主线程

    目录 概览 主线程 怎么来控制主线程 主线程和main()函数的关系 主线程中的死锁(单个线程) 概览 前段时间有同事提到了主线程这个名词,但当时我们说的主线程是指Java Web程序中每一个请求进来 ...

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

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

随机推荐

  1. TRS_WCM(拓尔思信息技术有限公司)内容协作平台平台置标经验攻略

    TRS_WCM置标过程中经验积累 版本V4.0-2014.6.24-穿越者7号 目录 1.嵌套模板置标 1 2.栏目名称超链接置标 1 3.列表循环输出文档标题包含超链接 1 4.取既定栏目下第一篇文 ...

  2. Apache启动失败,请检查相关配置。MySQL5.1已启动成功

    解决办法 一: 把左下角的SSL钩上了,如果你没有用证书,就把那个去掉,有的朋友去掉就可以了.也可能再装了证书钩上SSL也可以用了. 二: 看了说的把SSL勾掉的办法,也解决不了.后来就去查卡巴,也没 ...

  3. td中的值自动换行

    设置td中的值自动换行在<td ></td> 中加上这样一句代码,可以简省设置,使长字符串换行.而不用设置width,height. style="word-wrap ...

  4. php学习之路:php在iconv功能 详细解释

    iconv函数库可以完毕各种字符集间的转换,是php编程中必不可少的基础函数库. 使用方法例如以下: $string = "亲爱的朋友欢迎訪问胡文芳的博客.希望给您带来一点点的帮助!&quo ...

  5. STM32W芯片的JTAG口用于GPIO

    使用过程中发现STM32W芯片在驱动液晶SPI液晶时,在调试状态下可以正常工作但在通常运行情况下却没有任何显示! 经查发现我使用的两个端口PC0和PC3的电平很不正常,拉不高. 所以我就怀疑到IO口问 ...

  6. 网站开发常用jQuery插件总结(二)弹出层插件Lightbox

    网站开发过程中,为了增加网站交互效果,我们有时需要在当前页面弹出诸如登陆.注册.设置等窗口.而这些窗口就是层,弹出的窗口就是弹出层.jQuery中弹出层插件很多,但有些在html5+css3浏览器下, ...

  7. 自己写CPU第九阶段(5)——实现负载存储指令2(改变运行阶段)

    我们会继续上传新书<自己动手写CPU>.今天是第42篇.我尽量每周四篇,可是近期已经非常久没有实现这个目标了,一直都有事.不好意思哈. 开展晒书评送书活动,在q=%E4%BA%9A%E9% ...

  8. linux find命令之exec

    find是我们很常用的一个Linux命令,但是我们一般查找出来的并不仅仅是看看而已,还会有进一步的操作,这个时候exec的作用就显现出来了. exec解释: -exec  参数后面跟的是command ...

  9. MVC Filter 实现方式和作用范围控制

    Asp.Net MVC Filter 实现方式和作用范围控制 MVC中的Filte 简单又优雅的实现了AOP ,在日志,权限,缓存和异常处理等方面用的比较多.但本文不是讨论Filter这些功能点,而是 ...

  10. c# in deep 之使用匿名方法的内联委托操作

    匿名方法允许我们指定一个内联委托的操作,为创建委托实例表达式的一部分.其可以对代码进行极度精简,当然可读性变得很差.下面看一个求平方根的例子. List<int> list = new L ...