80. Code Review: Синхронизация критической секции в двух потоках #
🔥 В текущем коде создаётся новый Object для синхронизации при каждом вызове doSome(), поэтому потоки синхронизируются на разных мониторах — критическая секция фактически не защищена. Кроме того, вызов new Service.doSome() некорректен по синтаксису, а main должен быть static.
class Main{
void main(){
execute(()->new Service.doSome());
execute(()->new Service.doSome());
}
}
class Service{
void doSome(){
Object obj = new Object();
//code
synchronized(obj){
//code
}
//code
}
}
Спойлеры к решению
Подсказки
💡 Не создавай монитор внутри метода — он будет разным для каждого вызова. Держи общий
💡 Запускай оба потока на одном и том же экземпляре
💡 Исправь сигнатуру
lock в поле экземпляра (или используй synchronized на this).💡 Запускай оба потока на одном и том же экземпляре
Service, иначе будут разные мониторы.💡 Исправь сигнатуру
main на public static void main(String[] args) и вызовы лямбд (service::doSome).Решение (альтернатива с synchronized-методом)
class Main {
public static void main(String[] args) {
Service service = new Service();
execute(service::doSome);
execute(service::doSome);
}
static void execute(Runnable r) {
new Thread(r).start();
}
}
class Service {
void doSome() {
// code
critical(); // критическая секция вызовом синхронизированного метода
// code
}
private synchronized void critical() {
// code (критическая секция)
}
}
- Синхронизация на
thisчерезsynchronized-метод обеспечивает взаимное исключение между потоками на одном экземпляре.