如果一个同步方法调用另一个同步方法,那么线程安全吗?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
如果一个同步方法调用另一个同步方法,那么线程安全吗?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
Answers:
是的,当您将方法标记为时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
不同步而在使用a ,因此线程A在工作时可以由线程A调用method1
。
method3
显示了不安全的线程操作,但是您对可重入同步很了解。
从Java教程网站http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
同一对象上的两个同步方法调用不可能交错。当一个线程正在执行对象的同步方法时,所有其他调用同一对象块的同步方法的线程(挂起执行),直到第一个线程用该对象完成。
当同步方法退出时,它将自动与之前对同一对象的同步方法的任何调用建立先发生关系。这样可以保证对对象状态的更改对所有线程都是可见的
因此,Java将确保如果2个线程正在执行同一方法,则这些方法将不会同时执行,而是一个接一个地执行。
但是您需要注意“活力”问题, http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
另外,无论您是否不必要地锁定,都会在使用此代码的代码中锁定整个对象,如果您的对象仅需要对一个变量的同步访问,则应锁定该变量。
synchronized (this.someVar)
您正在看的参考位于的对象someVar
。区别非常重要。