Блокировка на уровне объекта
Реализована блокировка на уровне объекта для доступа к устройству:
private static Object device_locker_ = new Object();
public Device getDevice() {
synchronized (device_locker_) {
return device_;
}
}
Вопрос, могут ли разные потоки в данном случае работать с устройством, вызывая разные методы через getDevice()?
Примеры:
getDevice().getDeviceInfo()
getDevice().changePIN()
getDevice().doSomething()
Т.е. гарантируется ли в данном случае, что только один поток может работать с устройством?
Ответы (1 шт):
гарантируется ли в данном случае, что только один поток может работать с устройством?
Нет. В представленном в вопросе коде гарантируется, что блок, экранированный с помощью synchronized не будет доступен для одновременного выполнения несколькими потоками. А всё остальное - по прежнему может выполняться параллельно.
В целом, код
getDevice().getDeviceInfo()
getDevice().changePIN()
getDevice().doSomething()
эквивалентен следующему:
device = getDevice(); // этот код всегда будет выполняться только одним потоком *.
device.getDeviceInfo(); // а здесь уже разрешено параллельное выполнение
// аналогично - для других примеров вызовов методов
- Строго говоря, этот код не является полным аналогом примеров выше. Первая строчка "эквивалента" не полностью будет выполнена в рамках одного потока. Присвоение результата работы метода
getDevice()уже не ограничено ключевым словомsynchronized, поэтому если device является разделяемой переменной - потоки станут конкурировать за её заполнение.
Если внутри методов getDeviceInfo(), doSomething(), etc... производятся действия, параллельное выполнение которых несколькими потоками может привести к нежелательным последствиям (например - отправка команд на устройство потенциально может привести к смешению данных и как следствие - к ошибке протокола обмена) - именно эти действия необходимо ограничивать выполнением в рамках одного потока.