Упрощение синхронизированного блока в Java
У меня возникли некоторые проблемы, когда я обдумываю концепцию синхронизированных блоков в Java. Я чувствую, что достаточно хорошо понял синхронизированные методы. Поэтому я подумал об аналогии, которая поможет мне понять синхронизированные блоки с точки зрения синхронизированных методов. Пожалуйста, дайте мне знать, если предложенная мною эквивалентность верна. Кроме того, я упомянул об этом только для нестатического синхронизированного блока. Однако, точки на статических синхронизированных блоках также приветствуются.
public void method()
{
//code snipppet A
synchronized(objRef)
{
//code snipppet B
}
//code snipppet C
}
Эквивалентно
public void method() {
//code snippet A
objRef.sync_method();
//code snippet C
}
В классе objRef:
public synchronized void sync_method() {
//code snippet B
}
Эта аналогия основана на логике, что синхронизированные блоки ведут себя так же, как синхронизированные методы. Это означает, что, как только поток получает блокировку на мониторе, он не позволяет другим потокам вмешиваться в его выполнение. Поток отказывается от управления только после того, как завершит выполнение всего синхронизированного метода.
2 ответа
Вы должны заметить, что в Java есть два типа синхронизированных блоков (синхронизация объектов и синхронизация классов). Существует два синхронизированных метода (статический и нестатический методы) и их эквивалентные синхронизированные блоки (класс и объект синхронизированные блоки соответственно). предположим, что мы имеем:
class MyClass{
public synchronized static void syncStaticMethod(){...}
public synchronized void syncNonStaticMethod(){...}
}
MyClass objRef = new MyClass();
1. Синхронизация объектов:
public void method() {synchronized(objRef) { ... }}
Эквивалентно
public void method() {objRef.syncNonStaticMethod();}
2. Класс синхронизации:
public void method() {synchronized(MyClass.class) { ... }}
Эквивалентно
public void method() {MyClass.syncStaticMethod();}
Существует вероятность того, что вы не все понимаете правильно. Например,
synchronized(objRef) {
objRef.nonsync_method();
... more code ...
}
не эквивалентно
objRef.sync_method();
потому что в первом случае блокировка покрывает большую часть кода. Эквивалентность существует между
synchronized void sync_method() {
// stuff
}
а также
void nonsync_method() {
synchronized (this) {
// stuff
}
}
В дальнейшем,
как только поток получает блокировку на мониторе, он не позволяет другим потокам вмешиваться в его выполнение
Вышесказанное может быть или не быть правдой, в зависимости от того, как мы интерпретируем неоднозначную формулировку. Поток, получивший блокировку, может легко позволить другим потокам вмешиваться в его выполнение: все, что требуется, это еще один фрагмент кода, не покрытый точно такой же блокировкой. Например,
int i;
synchronized void sync_method() {
i = 0;
System.out.println(i);
}
void nonsync_method() {
i = 42;
}
Призыв к sync_method()
может печатать как 0, так и 42.