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
-метод обеспечивает взаимное исключение между потоками на одном экземпляре.