从另一个同步方法调用同步方法是否安全?
如果一个同步方法调用另一个同步方法,它是线程安全的吗?
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
-
同一对象上的两个同步方法的调用不可能交错。 当一个线程正在执行一个对象的同步方法时,所有其他调用同一对象的同步方法的线程将阻塞(挂起执行),直到第一个线程完成对象。
-
当一个同步方法退出时,它会自动build立一个发生之前的关系,以及随后调用同一个对象的同步方法。 这保证了对所有线程都可见的对象状态的改变
所以Java将确保如果2个线程正在执行相同的方法,这些方法将不会一个一个地执行,而是一个接一个地执行。
但是您需要了解Liveness问题,请http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
而且,无论你是否在不停地locking,导致在你使用这个locking整个对象的代码中,如果你的对象只需要同步访问一个variables,你应该locking该variables。