如果synchronized方法调用另一个同步方法,它是否是线程安全的?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
答案 0 :(得分:96)
是的,当您将方法标记为synchronized
时,您实际上是这样做的:
void method1() {
synchronized (this) {
method2()
}
}
void method2() {
synchronized (this) {
}
}
当线程调用从method1进入method2时,它将确保它保持对this
的锁定,它已经存在,然后它就可以通过。
当线程直接进入method1或method2时,它将阻塞,直到它可以获得锁定(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
是不同步的,因此当线程B在method1
中工作时,线程A可以调用它
答案 1 :(得分:5)
用synchronized标记的方法是另一个同步方法线程安全。
一般来说,不可能这么说。这取决于方法的作用,以及相同和其他类的其他方法。
但是,我们可以确定不同线程对同一对象的method1和method2的调用不会同时执行。根据方法的作用,这个可能足以说明该类对于这些方法是线程安全的。
答案 2 :(得分:1)
来自Java Tutorials网站http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
同一对象的两次同步方法调用不可能进行交错。当一个线程正在为对象执行同步方法时,所有其他线程调用同一对象的同步方法(暂停执行)直到第一个线程完成对象。
当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立一个before-before关系。这可以保证所有线程都可以看到对象状态的更改
因此,Java将确保如果2个线程正在执行相同的方法,那么这些方法将不会一个接一个地执行。
但您需要了解活动问题http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
而且你是否在不经意地锁定,导致你使用这个的代码,它会锁定整个对象,如果你的对象只需要对一个变量进行同步访问,你应该锁定该变量。 / p>