Могут ли два synchronized-метода одного объекта выполняться параллельно, если они работают с разными полями?

«Могут ли два synchronized-метода одного объекта выполняться параллельно, если они работают с разными полями?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, не могут. Ключевое слово synchronized на уровне метода (нестатического) блокирует весь объект (this). Это означает, что пока один поток выполняет любой synchronized-метод объекта, все другие потоки будут заблокированы при попытке войти в любой другой synchronized-метод этого же объекта, даже если методы оперируют разными данными.

Проблема: Это создает излишнюю конкуренцию и может снижать производительность.

Решение: Использовать отдельные объекты-мониторы (lock objects) для защиты независимых данных через synchronized-блоки.

Пример:

public class ImprovedExample {
    private final Object lockForDataA = new Object(); // Монитор 1
    private final Object lockForDataB = new Object(); // Монитор 2
    private List<String> dataA = new ArrayList<>();
    private List<String> dataB = new ArrayList<>();

    public void modifyA() {
        // Блокирует только операции с dataA
        synchronized (lockForDataA) {
            dataA.add("value");
            // Длинная операция с dataA...
        }
    }

    public void modifyB() {
        // Блокирует только операции с dataB
        // Может выполняться ПАРАЛЛЕЛЬНО с modifyA()
        synchronized (lockForDataB) {
            dataB.add("other value");
            // Длинная операция с dataB...
        }
    }
}

Важно: Для атомарных операций над отдельными полями часто лучше использовать классы из java.util.concurrent.atomic (например, AtomicInteger), которые обеспечивают потокобезопасность без явной блокировки.