黑马程序员技术交流社区

标题: 同步死锁问题 [打印本页]

作者: Tesla时光    时间: 2012-9-9 02:02
标题: 同步死锁问题
本帖最后由 翁发达 于 2012-9-9 21:34 编辑

话说要实现死锁,就是要锁中嵌套了非同一把锁.
下面我明明同步中嵌套了不同锁,且顺序不一样,
本来两个锁你抢我,我抢你,应该是可以死锁的,为什么这里不行?
我还让其得到一个锁先睡眠一会,可以还是不行
public class ShiSuo
{
public static void main(String[] args)
{
  Suo r =new Suo();
  Thread  t =new Thread(r);
  Thread  t1 =new Thread(r);
  t.start();
  try{Thread.sleep(10);}catch(Exception e){}
  r.flag=false;
  t1.start();
}
}
class Suo implements Runnable
{
private int a =1000;
Object obj = new Object();
boolean flag = true;
public  void run()
{
  while(true)
   {
  if(flag)
  {
   synchronized(obj)//这里是先obj锁,再this也就是本类对象锁.
   {
    try{Thread.sleep(10);}catch(Exception e){}
    synchronized(this)
    {
     System.out.println(Thread.currentThread().getName()+":  "+(a--));
    }
   }
  }
  else
  {
   sell();
  }
  }
}
public synchronized void sell()//而这里是先本对象锁,再obj对象锁.
{
  try{Thread.sleep(10);}catch(Exception e){}
  synchronized(obj)
  {
   System.out.println(Thread.currentThread().getName()+":  "+(a--));
  }
}
}

作者: 牛杨    时间: 2012-9-9 10:36
首先我要说的是,死锁并不是每次运行程序的时候都会发生的。
对于楼主的代码,每次运行都没有出现死锁的 是因为你的while循环放的地方不对。
应该把while(true)放到在if子句里面;并且在else子句里面也应该放一个while(true) 。
希望对楼主有帮助
作者: 杨震    时间: 2012-9-9 10:40
  1. import java.awt.*;

  2. public class ShiSuo {

  3.         public static void main(String[] args) {
  4.                 Suo r = new Suo();
  5.                 Thread t = new Thread(r, "t");
  6.                 Thread t1 = new Thread(r, "t1");
  7.                 t.start();
  8.                 try {
  9.                         Thread.sleep(200);//这里时间要短,但不能没有,没有的话,t线程没有执行,t.flag=false执行后,两个纯种就都只执行sell了,不会死锁;如果时间太长,t1线程不起动,开始也不会死锁,如果这里睡眠时间小于下面obj锁的代码里面的睡眠时间,则一开始就死锁了;
  10.                 } catch (Exception e) {
  11.                 }
  12.                 r.flag = false;
  13.                 t1.start();
  14.         }
  15. }

  16. class Suo implements Runnable {
  17.         private int a = 1000;
  18.         Object obj = new Object();
  19.         boolean flag = true;

  20.         public void run() {
  21.                 while (true) {
  22.                         if (flag) {
  23.                                 synchronized (obj)// 这里是先obj锁,再this也就是本类对象锁.
  24.                                 {
  25.                                         try {
  26.                                                 Thread.sleep(200);//这里时间要设置长一些,获取了obj锁之后,多等会,等待flag变为false,让t1这个线程执行sell代码,获取this锁,这样就发生了死锁;
  27.                                         } catch (Exception e) {
  28.                                         }
  29.                                         synchronized (this) {
  30.                                                 System.out.println(Thread.currentThread().getName()
  31.                                                                 + ":  " + (a--));
  32.                                                 System.out.println("flag = " + flag);
  33.                                         }
  34.                                 }
  35.                         } else {
  36.                                 sell();
  37.                         }
  38.                 }
  39.         }

  40.         public synchronized void sell()// 而这里是先本对象锁,再obj对象锁.
  41.         {
  42.                 try {
  43.                         Thread.sleep(10);
  44.                 } catch (Exception e) {
  45.                 }
  46.                 synchronized (obj) {
  47.                         System.out
  48.                                         .println(Thread.currentThread().getName() + ":  " + (a--));
  49.                         System.out.println("flag = " + flag);
  50.                 }
  51.         }
  52. }
复制代码

作者: 杨震    时间: 2012-9-9 10:41
  1. import java.awt.*;

  2. public class ShiSuo {

  3.         public static void main(String[] args) {
  4.                 Suo r = new Suo();
  5.                 Thread t = new Thread(r, "t");
  6.                 Thread t1 = new Thread(r, "t1");
  7.                 t.start();
  8.                 try {
  9.                         Thread.sleep(200);//这里时间要短,但不能没有,没有的话,t线程没有执行,t.flag=false执行后,两个纯种就都只执行sell了,不会死锁;如果时间太长,t1线程不起动,开始也不会死锁,如果这里睡眠时间小于下面obj锁的代码里面的睡眠时间,则一开始就死锁了;
  10.                 } catch (Exception e) {
  11.                 }
  12.                 r.flag = false;
  13.                 t1.start();
  14.         }
  15. }

  16. class Suo implements Runnable {
  17.         private int a = 1000;
  18.         Object obj = new Object();
  19.         boolean flag = true;

  20.         public void run() {
  21.                 while (true) {
  22.                         if (flag) {
  23.                                 synchronized (obj)// 这里是先obj锁,再this也就是本类对象锁.
  24.                                 {
  25.                                         try {
  26.                                                 Thread.sleep(200);//这里时间要设置长一些,获取了obj锁之后,多等会,等待flag变为false,让t1这个线程执行sell代码,获取this锁,这样就发生了死锁;
  27.                                         } catch (Exception e) {
  28.                                         }
  29.                                         synchronized (this) {
  30.                                                 System.out.println(Thread.currentThread().getName()
  31.                                                                 + ":  " + (a--));
  32.                                                 System.out.println("flag = " + flag);
  33.                                         }
  34.                                 }
  35.                         } else {
  36.                                 sell();
  37.                         }
  38.                 }
  39.         }

  40.         public synchronized void sell()// 而这里是先本对象锁,再obj对象锁.
  41.         {
  42.                 try {
  43.                         Thread.sleep(10);
  44.                 } catch (Exception e) {
  45.                 }
  46.                 synchronized (obj) {
  47.                         System.out
  48.                                         .println(Thread.currentThread().getName() + ":  " + (a--));
  49.                         System.out.println("flag = " + flag);
  50.                 }
  51.         }
  52. }
复制代码

作者: 杨震    时间: 2012-9-9 10:43
卡了,重复发贴了
作者: 朱烈葵    时间: 2012-9-9 10:48
楼主啊 楼主啊  其实很很很简单,

  Thread  t =new Thread(r);
  Thread  t1 =new Thread(r);
  t.start();
  try{Thread.sleep(10);}catch(Exception e){}
  r.flag=false;

看到没  你暂停了,当你开启第二个线程的时候,第一个已经完事了,所以没人抢,怎么会死锁呢,想死锁,把那儿暂停去掉,准死
作者: 杨震    时间: 2012-9-9 10:49
主要是要保证你的两个线程里面一个执行if里面的内容,另一个线程执行else的内容,但你开始的时间设置,达不到这个要求
作者: 杨震    时间: 2012-9-9 10:57
牛杨 发表于 2012-9-9 10:36
首先我要说的是,死锁并不是每次运行程序的时候都会发生的。
对于楼主的代码,每次运行都没有出现死锁的 是 ...

我想复杂了,你讲的简单正确
作者: 杨震    时间: 2012-9-9 11:02
[code]
        private int a = 1000;
        Object obj = new Object();
        boolean flag = true;

        public void run() {

                if (flag) {
                        while (true) {
                                synchronized (obj)// 这里是先obj锁,再this也就是本类对象锁.
                                {
                                        try {
                                                Thread.sleep(10);
                                        } catch (Exception e) {
                                        }
                                        synchronized (this) {
                                                System.out.println(Thread.currentThread().getName()
                                                                + ":  " + (a--));
                                                System.out.println("flag = " + flag);
                                        }
                                }
                        }
                } else {
                        while (true) {
                                sell();
                        }
                }
        }

        public synchronized void sell()// 而这里是先本对象锁,再obj对象锁.
        {
                try {
                        Thread.sleep(10);
                } catch (Exception e) {
                }
                synchronized (obj) {
                        System.out
                                        .println(Thread.currentThread().getName() + ":  " + (a--));
                        System.out.println("flag = " + flag);
                }
        }
[/code

按二楼讲的,while要换位置,这样线程一起动就保证t线程执行的是if里面的,然后flag变为false,保证了t1执行的是else也就是sell,这样就死锁了
作者: 牛杨    时间: 2012-9-9 14:30
本帖最后由 牛杨 于 2012-9-9 14:32 编辑
杨震 发表于 2012-9-9 10:57
我想复杂了,你讲的简单正确


谢谢 ! 求加分啊
作者: 崔朋朋    时间: 2012-9-9 16:05
本帖最后由 崔朋朋 于 2012-9-9 17:55 编辑

程序读到 synchronized 关键字时会拿到对象的锁, 当 synchronized代码块执行完毕后会释放对象锁,

1.当t.start();执行后,t线程会一直执行执行while(true)里边的if(){...}代码块。程序是先执行 if()语句中的判断,再拿到对象的锁,if(){...}代码块执行结束后释放对象锁

2.t1.start();执行后,t1线程会一直执行执行while(true)里边的else(){...}代码块。程序也是先执行 if()语句中的判断,再拿到对象的锁,else(){...}代码块执行结束后释放对象锁。

线程的执行具有不稳定性,线程何时中断不受程序控制
之所以不出现死锁,是存在这种可能:每次都是t线程 正在执行判断 或 释放对象锁后,t线程中断,t1线程正好运行且拿到对象锁; 而当t1线程 正在执行判断 或 释放对象锁后,t1线程中断,t线程正好执行且拿到对象锁。  所以没有出现死锁现象。








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