Намного лучше, чем помещать synchronized
везде, - это тщательно продумать, какие инварианты нужны вашим классам, а затем синхронизировать их настолько, чтобы обеспечить эти инварианты. Если вы чрезмерно синхронизируете, вы создаете два риска:
- тупиковый
- проблемы с живостью
тупик, который все знают. Проблемы с живучестью связаны не со стоимостью синхронизации, а с тем фактом, что если вы синхронизируете глобально все в многопоточном приложении, то многие потоки будут заблокированы в ожидании получения монитора, потому что другой поток касается чего-то не связанного, но используя тот же монитор.
Если вы хотите использовать ключевое слово везде для безопасности, тогда я рекомендую использовать final
вместо synchronized
. :)
Все, что вы можете сделать final
, способствует лучшей безопасности потоков и упрощает рассуждения о том, что инварианты должны поддерживаться замками. Для примера, скажем, у вас есть этот тривиальный класс:
public class SimpleClass {
private volatile int min, max;
private volatile Date startTime;
// Assume there are many other class members
public SimpleClass(final int min, final int max) {
this.min = min;
this.max = max;
}
public void setMin(final int min) {
// set min and verify that min <= max
}
public void setMax(final int max) {
// set max and verify that min <= max
}
public Date getStartTime() {
return startTime;
}
}
При использовании вышеуказанного класса при настройке min или max вам необходимо выполнить синхронизацию. Код выше не работает. Какой инвариант у этого класса? Вы должны убедиться, что min <= max
всегда, даже когда несколько потоков вызывают setMin
или setMax
.
Предполагая, что это большой класс со многими переменными, и вы синхронизируете все, тогда, если один поток вызывает setMin
, а другой поток вызывает getStartTime
, второй поток будет излишне заблокирован до возврата setMin
. Если вы сделаете это с классом, состоящим из множества членов, и при условии, что только некоторые из этих членов участвуют в инвариантах, которые должны быть защищены, то синхронизация всего вызовет множество проблем жизнеспособности такого рода.