黑马程序员技术交流社区

标题: 死锁还是没搞明白 [打印本页]

作者: ln0491    时间: 2015-9-16 09:22
标题: 死锁还是没搞明白
昨天看了视频,自己写了下,就不是出来

作者: jiaweizhang    时间: 2015-9-16 10:51
这时我学习总结的,写出了一个例子

死锁出现的情况:同步嵌套同步

死锁例子:

public class DeadLock implements Runnable {
    private int flag;        //标识线程交替
    DeadLock(int flag){
            this.flag = flag;
    }
    static Object o1 = new Object(),o2 = new Object();        //定义两把锁
    public void run(){
        System.out.println("flag=" + flag +"---"+ Thread.currentThread());        //打印当前线程信息
        // 当flag==1锁住o1
        if (flag == 1) {
                synchronized (o1) {
                            System.out.println("101");
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 只要锁住o2就完成
                synchronized (o2) {
                    System.out.println("1");
                }
            }        
        }
        // 如果flag==0锁住o2
        if (flag == 0) {
            synchronized (o2) {
                try {
                        System.out.println("202");
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 只要锁住o1就完成
                synchronized (o1) {
                    System.out.println("0");
                }
            }
        }
    }
        public static void main(String[] args) {
        // 实例2个线程类
        DeadLock td1 = new DeadLock(0);
        DeadLock td2 = new DeadLock(1);

        // 开启2个线程
        Thread t1 = new Thread(td1);
        Thread t2 = new Thread(td2);
        t1.start();
        t2.start();
    }
}

运行结果:

flag=0--->Thread[Thread-0,5,main]
flag=1--->Thread[Thread-1,5,main]
202
101



flag=1--->Thread[Thread-1,5,main]
flag=0--->Thread[Thread-0,5,main]
101
202

理解:两个线程执行时,当Thread-0线程持有o1锁,线程Thread-1线程持有o2锁,

      此时两个锁都没有释放,Thread-0线程嵌套的同步代码块要获取o2锁,Thread-1线程嵌套的同步代码块要获取o1锁,

      但两个锁已被占用,均无法获取,程序到这里停止不动,就造成了死锁的情况

避免死锁:网络解释

    让所有的线程按照同样的顺序获得一组锁。这种方法消除了 X 和 Y 的拥有者分别等待对方的资源的问题。

  将多个锁组成一组并放到同一个锁下。前面Java线程死锁的例子中,可以创建一个银器对象的锁。于是在获得刀或叉之前都必须获得这个银器的锁。

  将那些不会阻塞的可获得资源用变量标志出来。当某个线程获得银器对象的锁时,就可以通过检查变量来判断是否整个银器集合中的对象锁都可获得。如果是,它就可以获得相关的锁,否则,就要释放掉银器这个锁并稍后再尝试。

  最重要的是,在编写代码前认真仔细地设计整个系统。多线程是困难的,在开始编程之前详细设计系统能够帮助你避免难以发现Java线程死锁的问题。
作者: ln0491    时间: 2015-9-16 11:56
jiaweizhang 发表于 2015-9-16 10:51
这时我学习总结的,写出了一个例子

死锁出现的情况:同步嵌套同步

谢谢,再慢慢理解下
作者: lizhichao    时间: 2015-9-16 12:04
电脑太好了也是一个错。首先你确定你是锁的嵌套吗。第二 你的锁对象是几个(你很有可能是把锁对象搞错了)。能不能把你写的代码弄出来看看。
作者: 球球_    时间: 2015-9-16 12:08
马上我们也学习线程了,我也不明白
作者: Hi不言而喻    时间: 2015-9-16 12:22
我们也快要学线程了
作者: 插兜    时间: 2015-9-16 13:01
二楼很棒
作者: 天涯莫名    时间: 2015-9-16 21:15
好高深,没看懂
作者: foreverfun    时间: 2015-9-16 21:18
死锁好像挺绕的,要先认真预习下
作者: 然后呢8908    时间: 2015-9-16 21:52
嗯,学习了
作者: stream_lin    时间: 2015-9-16 21:58
据我的 认识 死锁是随机出现的吧。  有时候会出现和谐的情况 就没问题 不知道楼主是不是遇到这种情况,还是我的技术太差 有误导你的成分在??
作者: cemabenteng    时间: 2015-9-16 22:13
锁内容比较重要,挺简单的,好好学
作者: 史世锋    时间: 2015-9-16 22:21
package com.itheima;

class MyLock
{
        //定义两个Lock对象,代表两把锁
        static MyLock  locka = new MyLock ();
        static MyLock  lockb = new MyLock ();
}
class DeadLock implements Runnable
{       
        //定义一个标识符
        boolean flag;
        DeadLock(boolean flag)
        {
                this.flag = flag;
        }
       
        @Override
        public void run()
        {
                if(flag)
                {
                        synchronized(MyLock.locka)
                        {
                                System.out.println("if locka");
                                //lockb被另一个线程持有
                                synchronized(MyLock.lockb)
                                {
                                        System.out.println("if lockb");
                                }
                        }
                }
                else
                {
                        synchronized(MyLock.lockb)
                        {
                                System.out.println("else lockb");
                                //locka被另一个线程持有
                                synchronized(MyLock.locka)
                                {
                                        System.out.println("else locka");
                                }
                        }
                }
        }
}
public class Test026
{

        /**
         * 死锁的出现时因为同步代码块中嵌套同步代码块
         * @param args
         */
        public static void main(String[] args)
        {
                DeadLock dl1 = new DeadLock(true);
                DeadLock dl2 = new DeadLock(false);       
               
                new Thread(dl1).start();
                new Thread(dl2).start();       
        }

}

作者: ln0491    时间: 2015-9-17 11:41
jiaweizhang 发表于 2015-9-16 10:51
这时我学习总结的,写出了一个例子

死锁出现的情况:同步嵌套同步

两个锁为什么要静态的,普通的为什么不行
作者: ln0491    时间: 2015-9-17 11:42
两个锁为什么要静态的,普通的为什么不行
作者: ln0491    时间: 2015-9-17 11:44
史世锋 发表于 2015-9-16 22:21
package com.itheima;

class MyLock

两个锁为什么要静态的,普通的为什么不行
作者: jiaweizhang    时间: 2015-9-17 12:10
ln0491 发表于 2015-9-17 11:44
两个锁为什么要静态的,普通的为什么不行

静态: 随着类的加载而加载---会随着类的消失而消失,生命周期最长
如果不是静态,你在代码中加入锁对象.toString(); 打印结果会是4个不同的地址
也就说相当于4把锁,当然锁不住,所有静态是保证锁对象只有两个
java.lang.Object@41bbee70
java.lang.Object@5b87a0b5
java.lang.Object@4f7c1837
java.lang.Object@554055b5
作者: ln0491    时间: 2015-9-17 13:42
jiaweizhang 发表于 2015-9-17 12:10
静态: 随着类的加载而加载---会随着类的消失而消失,生命周期最长
如果不是静态,你在代码中加入锁对象. ...

明白了,谢谢
作者: jiaweizhang    时间: 2015-9-17 13:45
ln0491 发表于 2015-9-17 13:42
明白了,谢谢

我也是看了很久才明白的{:2_32:}
作者: 小二儿    时间: 2015-9-17 20:44
线程、、、、、、、、重点!学习二楼,谢谢
作者: 乔友为    时间: 2015-9-17 21:35
...........
作者: 乔友为    时间: 2015-9-17 21:36
慢慢来 ,理解
作者: 史世锋    时间: 2015-9-17 22:49
ln0491 发表于 2015-9-17 11:44
两个锁为什么要静态的,普通的为什么不行

定义成静态只是为了方便使用,可以直接用类名调用。
作者: ln0491    时间: 2015-9-18 00:19
谢谢各位。。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2