Если синхронизированный метод вызывает другой синхронизированный метод, является ли он безопасным по потоку?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
Если синхронизированный метод вызывает другой синхронизированный метод, является ли он безопасным по потоку?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
Да, когда вы отмечаете методы как synchronized
, вы действительно это делаете:
void method1() {
synchronized (this) {
method2()
}
}
void method2() {
synchronized (this) {
}
}
Когда вызов потока попадает в метод2 из метода1, он гарантирует, что он удерживает блокировку до this
, которая уже будет, а затем она может пройти.
Когда поток попадает непосредственно в method1 или method2, он блокируется, пока не сможет получить блокировку (this
), а затем он войдет.
Как отмечено Джеймсом Блэком в комментариях, вам нужно знать, что вы делаете внутри тела метода.
private final List<T> data = new ArrayList<T>();
public synchronized void method1() {
for (T item : data) {
// ..
}
}
public void method3() {
data.clear();
}
Вдруг это не потокобезопасно, потому что вы смотрите на ConcurrentModificationException
в будущем, потому что method3
несинхронизирован и, следовательно, может быть вызван потоком A, а Thread B работает в method1
.
Является ли метод помеченным с синхронизированным вызовом другим безопасным потоком синхронизированного метода.
В общем, нельзя сказать. Это зависит от того, что делают методы, и от каких других методов используются одни и те же классы.
Однако мы можем быть уверены, что вызовы метода 1 и метода2 на одном и том же объекте, выполненные разными потоками, не будут выполняться одновременно. В зависимости от того, что делают эти методы, этого может быть достаточно, чтобы сказать, что класс является потокобезопасным по отношению к этим методам.
На сайте Java Tutorials http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Невозможно чередование двух вызовов синхронизированных методов на одном объекте. Когда один поток выполняет синхронизированный метод для объекта, все другие потоки, которые вызывают синхронизированные методы для одного и того же блока объектов (приостанавливают выполнение) до тех пор, пока первый поток не будет выполнен с объектом.
когда синхронизированный метод завершается, он автоматически устанавливает связь между событиями и последующим вызовом синхронизированного метода для одного и того же объекта. Это гарантирует, что изменения состояния объекта будут видны для всех потоков
Таким образом, Java гарантирует, что если 2 потока выполняют один и тот же метод, методы не будут выполняться одновременно, а один за другим.
Но вам нужно знать о проблеме Liveness, http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
А также независимо от того, блокируете ли вы незаметно, в коде, который вы использовали this, который блокирует весь объект, если вашему объекту нужен только доступ к синхронизации для одной переменной, вы должны просто заблокировать эту переменную.