从另一个同步方法调用同步方法是否安全?

如果一个同步方法调用另一个同步方法,它是线程安全的吗?

void synchronized method1() { method2() } void synchronized method2() { } 

是的,当你把方法标记为synchronized ,你真的是这样做的:

 void method1() { synchronized (this) { method2() } } void method2() { synchronized (this) { } } 

当线程调用从方法1进入方法2时,它将确保它保持this的locking,这将已经,然后它可以通过。

当线程直接进入方法1或方法2时,它将阻塞,直到它可以获得锁( this ),然后它将进入。

正如在评论中詹姆斯·布莱克(James Black)所指出的那样,你必须意识到你在方法体内做了什么。

 private final List<T> data = new ArrayList<T>(); public synchronized void method1() { for (T item : data) { // .. } } public void method3() { data.clear(); } 

突然间,它不是线程安全的,因为您将来会看到一个ConcurrentModificationException method3 ,因为method3是不同步的,因此Thread B可以在method1工作,而线程A可以调用它。

用synchronized调用另一个同步方法的方法是线程安全的。

一般来说,这是不可能的。 这取决于这些方法的作用,以及同一类和其他类中的其他方法。

但是,我们可以肯定的是,不同线程对同一对象的方法1和方法2的调用不会同时执行。 根据这些方法的作用,这可能足以说明这个类对于这些方法是线程安全的。

从Java教程网站http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

  1. 同一对象上的两个同步方法的调用不可能交错。 当一个线程正在执行一个对象的同步方法时,所有其他调用同一对象的同步方法的线程将阻塞(挂起执行),直到第一个线程完成对象。

  2. 当一个同步方法退出时,它会自动build立一个发生之前的关系,以及随后调用同一个对象的同步方法。 这保证了对所有线程都可见的对象状态的改变

所以Java将确保如果2个线程正在执行相同的方法,这些方法将不会一个一个地执行,而是一个接一个地执行。

但是您需要了解Liveness问题,请http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html

而且,无论你是否在不停地locking,导致在你使用这个locking整个对象的代码中,如果你的对象只需要同步访问一个variables,你应该locking该variables。