Изучение потоков и параллелизма. Рассмотрим следующий код:Недостатки вложенных синхронизированных блоков
class A {
protected final Object lock = new Object();
public void remove(Object obj){
synchronized(lock){
// remove the object
}
}
public void add(Object obj){
synchronized(lock){
// add the object
}
}
}
Этот код потокобезопасно в том смысле, что нет двух разных потоков могут add
или remove
в то время как один поток находится в процессе добавления или удаления.
Теперь рассмотрим следующий sublcass А:
class B extends A {
public void update1(Object original, Object newObj){
remove(original);
add(original);
}
public void update2(Object original, Object newObj){
synchronized(lock) {
remove(original);
add(newObj);
}
}
}
Класс B
должен реализовать поточно-update
метод. Теперь, насколько я знаю, update1
не является потокобезопасным, потому что операция не является атомарной, т. Е. Нет синхронизации между выполнением remove
и add
(исправьте меня, если не так).
update2
правильный способ реализации поточно-безопасного метода update
? Есть ли недостатки наличия вложенных синхронизированных блоков по сравнению с тем же lock
?
Я думаю, что такой код чреват опасностью тупика. Вам будет лучше использовать более современные дополнения к JVM: параллельный пакет, ExcecutorService и parallelStream, если вы до JDK 8. – duffymo
Оба «update1» и «update2» являются потокобезопасными. Наличие 'synchronized (lock)' in 'update2' является излишним, потому что вы уже настроили синхронизацию в методах класса A. После того, как поток обработает блокировку, он может проходить через весь следующий блок «synchronize» без необходимости его приобретения. – ortis
@ortis Я думаю, что они хотят удалить и добавить, чтобы сделать транзакцию. В 'update1' другой поток может удалить или добавить между вызовами. –