2014-02-07 91 views
0

我有3个类,如下所示。我已经使用synchronized(b)这样,一个对象获取B对象上的锁,并且在A中的foo方法完成工作之前,将不会调用b中的任何方法。Java多线程同步(对象)

但是,这似乎不起作用(见最后的输出)。事实上,racethread能够调用对象b上的方法。

注意:您可以创建一个简单的java项目,并将下面的代码添加到一个文件中以尝试并执行。

package com.threads.main.deadlock;

class A { 
    void foo(B b) { 
     synchronized (b) { // Trying to get lock on b here 
      String name = Thread.currentThread().getName(); 
      System.out.println(name + " entered A.foo"); 
      try { 
       Thread.sleep(1000); 
      } catch (Exception e) { 
       System.out.println("A Interrupted"); 
      } 
      System.out.println(name + " trying to call B.last()"); 
      b.last(); 
     } 
    } 

    synchronized void last() { 
     System.out.println("Inside A.last"); 
    } 
} 
class B { 
    void bar(A a) { 
     synchronized (a) { 

      String name = Thread.currentThread().getName(); 
      System.out.println(name + " entered B.bar"); 
      try { 
       Thread.sleep(1000); 
      } catch (Exception e) { 
       System.out.println("B Interrupted"); 
      } 
      System.out.println(name + " trying to call A.last()"); 
      a.last(); 
     } 
    } 

    synchronized void last() { 
     System.out.println("Inside B.last"); 
    } 
} 
public class Deadlock implements Runnable { 
    A a = new A(); 
    B b = new B(); 

    Deadlock() { 
     Thread.currentThread().setName("MainThread"); 
     Thread t = new Thread(this, "RacingThread"); 
     t.start(); 

     new Thread(new Dum(a)).start(); 
     a.foo(b); // get lock on a in this thread. 
     System.out.println("Back in main thread"); 
    } 

    public void run() { 
     b.bar(a); // get lock on b in other thread. 
     System.out.println("Back in other thread"); 
    } 

    public static void main(String args[]) { 
     new Deadlock(); 
    } 
} 

class Dum implements Runnable { 

    A a = null; 

    public Dum(A a) { 
     this.a = a; 
    } 

    @Override 
    public void run() { 
     int i =0; 
     while (i++ < 5) { 
      System.out.println("Trying a.last .. dum"); 
      a.last(); 
     } 
    } 

} 

输出:

RacingThread entered B.bar 
Trying a.last .. dum 
MainThread entered A.foo 
RacingThread trying to call A.last() 
MainThread trying to call B.last() 
Inside B.last 
Inside A.last 
Back in other thread 
Back in main thread 
Inside A.last 
Trying a.last .. dum 
Inside A.last 
Trying a.last .. dum 
Inside A.last 
Trying a.last .. dum 
Inside A.last 
Trying a.last .. dum 
Inside A.last 
+0

真的不清楚你在这里期待什么;没有什么会导致僵局。 –

+2

可能是另一种误解2线程需要在同一个对象监视器上进行同步的情况,并且没有办法“锁定对象”。 – Kayaman

+0

@Kayaman,你可否请求详细说明'2个线程需要在同一个对象监视器上同步',你可以修改这个类并显示它。很难理解,因为我是多线程新手。另外,当我添加同步(对象)对象时,下一点将被刚刚进入对象监视器的线程锁定;并且在线程释放监视器之前,锁定对象内的任何方法都不会被其他线程访问? – Zeus

回答

0

你的A和B线程使用不同的对象在他们的方法同步。

所以你的假设

一个对象获取B对象上的锁,没有在B 的方法将被调用,直到在一个Foo方法完成扫尾工作。

是错误的。 A.foo运行时,它使用B的实例进行同步。但是,这只能阻止B.last的并行运行,因为B.foo在A上有一个同步块。但是当然,当A.foo尝试调用b.last时,它不会导致任何阻塞,因为A.foo已经在b的监视器内。

如果你有这样的方法:

synchronized void last() { 
} 

这是basicly等同于:

void last() { 
    synchronized(this){ //so in case of Class B it means: this = the B instance 
    } 
} 

我建议名称的所有线程,并添加Thread.currentThread()的getName。 ()到每一个单一的系统,你会更好地理解它。