日期:2014-05-20  浏览次数:20675 次

怎么想都想不明白。明明按视频教程里写的是死锁,怎么还能循环呢?
class Lie
 {
  public static void main(String[] args)
  {
  Dear d=new Dear();
  new Thread(d).start();
  try
  {
  Thread.sleep(1);
  }
  catch(Exception e)
  {
  e.printStackTrace();
  }
  d.b=true;
  new Thread(d).start();
 
  }
}

class Dear implements Runnable
{
int i=180;
Object obj=new Object();
Boolean b=false;
public void run()

{
if(b==false)
{
while(true)
sun();
}
else
{
while(true)
{
synchronized(obj)
{
try
{
Thread.sleep(10);
}
catch(Exception e)
{
e.printStackTrace();
}
synchronized(this)
{
if(i>0)
{

System.out.println("run this:"+Thread.currentThread().getName()+
"i:"+i);
i--;
}
 }
 }
 }
 }

public synchronized void sun()
{
synchronized(obj)
{
 
if(i>0)
{
try
{
Thread.sleep(10);
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println("sun is:"+Thread.currentThread().getName()+
"i:"+i);
i--;

}
}
}






始终不明白,检查了好几遍,头疼,请高手指点。。
thread class

------解决方案--------------------
代码里面有两个锁,一个当前对象锁,这里用this表示,另外一个是object 锁。你把sun方法改一下。改成下面的。首先要明白怎么才能让这个程序死锁。条件就是一个线程(A)占有object锁,然后要申请this锁。另外一个线程(B)占有this锁,又要申请object锁。下面代码的意思就是进入sun方法后,你就占有this锁,然后要去申请object锁。中间让线程B休息下,给线程A时间去执行run方法中的esle语句,进入else后线程A就占有了object锁,然后它又要去申请this锁。这样就形成了线程A和B 相互等待的过程。
public synchronized void sun()
{

try
{
Thread.sleep(10);
}
catch(Exception e)
{
e.printStackTrace();
}

synchronized(obj)
{
System.out.println("go to sun b=false");
if(i>0)
{

System.out.println("sun is:"+Thread.currentThread().getName()+
"i:"+i);
i--;

}
}
}

现在来分析下你的疑问,为什么还能循环。我把你程序打印的结果列出来,当然是随即。每次结果不一样。
sun is:Thread-0i:180
sun is:Thread-0i:179
sun is:Thread-0i:178
sun is:Thread-0i:177
sun is:Thread-0i:176
sun is:Thread-0i:175
sun is:Thread-0i:174
sun is:Thread-0i:173
sun is:Thread-0i:172
比方说第一线程(A),默认b==false。第二个线程(B),b==true。
A先执行,走到方法sun中,因为加了synchronized,就是得到this锁,然后执行下面的synchronized(obj)语句,这个时候有占用了obj锁,死锁的临界区就在下面的C位置。要产生死锁,就得在A要执行C语句块以下的代码的时候,线程B同时进入了run方法中else语句,并且获得了obj锁,B接着申请this锁。this锁又被A占用了,A又在申请obj锁。大家都在等,那就一起等死吧。
public synchronized void sun()
//死锁临界区间(C)
{
synchronized(obj)。
由于C中没有任何时间间隔,所以A就同时占有了两把锁,这个时候线程B 没机会执行run方法中的else语句,因为它一直在等待obj锁的释放。线程A接着执行,打出sun is:Thread-0i:180。 执行完后线程A要释放锁object,this。这个时候返回到while(true) sun();处。其实我的理解这个时候A,B都有机会执行相应的代码块,但是根据程序打印的结果,接着A线程会继续执行,这样就重复上面的代码,至于什么时候结束,就是上面提到的临界区,产生死锁了,程序就死在那里了。这样看来你的代码其实是产生了死锁,只是时间比较慢。我上面该的代码就是让他死得更块点。