如果一个同步方法调用另一个同步方法,它是否线程安全?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
如果一个同步方法调用另一个同步方法,它是否线程安全?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
是的,当您将方法标记为synchronized
时,实际上是这样做的:
void method1() {
synchronized (this) {
method2()
}
}
void method2() {
synchronized (this) {
}
}
当线程从方法1调用进入方法2时,它会确保持有锁定的this
,因为它已经拥有该锁,所以它可以直接通过。
现在当另一个线程尝试直接进入方法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();
}
由于method3
未同步,因此当线程B在method1
中工作时,线程A可能会调用method3
,从而导致线程不安全,并出现ConcurrentModificationException
。
method3
显示了不安全的线程操作,但你对可重入同步的理解是正确的。 - pickypg一个用synchronized标记的方法调用另一个用synchronized标记的方法,这个类是否线程安全。
通常情况下,无法确定。这取决于方法的功能以及同一和其他类上的其他方法的功能。
但是,我们可以确定,不同线程在相同对象上对method1和method2的调用不会同时执行。根据方法的功能,这可能足以说明该类关于这些方法是线程安全的。
来自Java教程网站http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
在同一个对象上调用同步方法时,两个synchronized方法的执行不可能交错进行。当一个线程正在执行对象的同步方法时,所有其他调用该对象的同步方法的线程都被阻塞(暂停执行),直到第一个线程完成为止。
同步方法退出时,它会自动与后续对相同对象调用的任何同步方法建立happens-before关系。这确保了对象状态的更改对所有线程都是可见的。
Java 会确保如果有2个线程执行相同的方法,方法不会同时执行,而会一个接着一个执行。
但你需要注意活性问题,http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
而且你也需要注意是否过度使用锁定,因为在你所使用的代码中this会锁定整个对象,如果你的对象只需要同步访问一个变量,你应该只锁定那个变量即可。
synchronized (this.someVar)
时,你是在查找someVar
所持有的对象的引用。这个区别非常重要。 - Stephen Cprivate final Object mSync; synchronized (this.mSync) {//some code}
- zeitgeist