2016-07-24 184 views
0

简而言之,我想知道这是否会改变行为。我假设是的,因为调用someMethod()会锁定整个对象,而不是只是列表对象?但我仍然对这个同步的东西很陌生,所以我想要一些更受教育的反馈。从同步块调用此同步方法可以吗?

的面前:

public void run() { 
    int i = 0; 

    while (!end) { 
     synchronized (list) { 
      while (list.size() == i) { 
       try { 
        list.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

的经过:

public void run() { 
    int i = 0; 

    while (!end) { 
     synchronized (list) { 
      while (list.size() == i) { 
       someMethod(); 
      } 
     } 
    } 
} 

public synchronized void someMethod() { 
    try { 
     list.wait(); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

回答

2

你是正确的 - 新的代码得到了不同的语义,为someMethod()确实在它被调用该命令的情况下同步(因此,该同步与list上的同步完全无关)。但是,拨打someMethod()的电话将在list上的监视器被保持时发生,因此对的拨打对list是“同等线程安全”。

另一方面,您现在已经介绍了多个线程同时直接呼叫someMethod()的可能性。由于对象本身的额外同步,您还引入了一个(可能不必要的)与其他线程发生死锁的可能性。我会推荐这个代替:

public void someMethod() { 
    synchronized (list) { 
     try { 
      list.wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

此方法现在无论是个人使用,通过run()被称为安全 - 请注意,它是安全的,你已经在同步对象上同步;线程不会阻塞自己。

+0

欣赏它,谢谢! – Badger

2

随着syncronized你不真的'锁定'一个对象。您只需确保在同一个特定对象上同步同步的访问权限是“锁定”的。

同步方法正在this上同步。

这意味着,如果某个对象list上输入syncronized块,你可以在第一


有些东西叫syncronized方法没有问题加以考虑:

此代码没有按” t产生死锁:

public void foo() { 
    synchronized (this) { 
     someMethod(); 
    } 
} 

public synchronized void someMethod() { 
    // ... 
} 

因为你已经有了“锁定”this ,但是这个:

public void foo() { 
    synchronized (list) { 
     someMethod(); 
    } 
} 

public synchronized void someMethod() { 
    // ... 
} 

可能会产生与其他线程的死锁!如果您在另一个​​部分输入​​部分,您必须非常小心。