На что синхронизируется поток при использовании ключевого слова synchronized в Java?

Ответ

Ключевое слово synchronized обеспечивает синхронизацию по монитору (внутреннему замку) объекта.

Правила:

  1. Нестатический synchronized-метод блокирует монитор объекта this, на котором вызван метод.
  2. Статический synchronized-метод блокирует монитор объекта класса (ClassName.class).
  3. Synchronized-блок позволяет явно указать объект-монитор.

Примеры:

public class Counter {
    private int count = 0;
    private final Object customLock = new Object();

    // Синхронизация по монитору объекта 'this'
    public synchronized void increment() {
        count++;
    }

    // Синхронизация по монитору класса Counter.class
    public static synchronized void staticMethod() {
        // ...
    }

    // Синхронизация по произвольному объекту
    public void decrement() {
        synchronized (customLock) {
            count--;
        }
    }
}

Важно: Для корректной взаимной блокировки все конкурирующие потоки должны использовать один и тот же объект-монитор.

Ответ 18+ 🔞

А, ну это же про синхронизацию, классика! Сейчас разжуем, как блядь, эту тему про synchronized, чтобы даже у мартышлюшки с бананом в жопе вопросов не осталось.

Смотри, ключевое слово synchronized — это как будто ты на дверь в сортир вешаешь табличку «ЗАНЯТО». Только вместо двери тут монитор (или, проще говоря, внутренний замок) у какого-то объекта. Пока один поток этот замок держит, остальные стоят и бздят в коридоре, ждут своей очереди.

Простые правила, которые надо в печёнках сидеть:

  1. Обычный synchronized-метод (не статический). Тут всё просто, как три копейки. Замок вешается на объект this — то есть на ту самую конкретную контору, у которой этот метод вызвали. Пока один чувак внутри, другие в эту же контору не пролезут.
  2. Статический synchronized-метод. А вот это уже замок не на конкретную контору, а на целый чертёж завода! То есть на объект класса (Counter.class). Если такой метод выполняется, он блокирует доступ для всех остальных статических синхронизированных методов этого класса, даже если экземпляров (this) дохуя и больше.
  3. Synchronized-блок. Это для самых хитрых жоп. Позволяет не всю дверь на замок закрывать (весь метод), а только сейф в углу. И главное — ты сам выбираешь, на какой именно сейф (объект-монитор) вешаешь замок.

Смотри, как это выглядит в коде, ёпта:

public class Counter {
    private int count = 0;
    private final Object customLock = new Object(); // Наш личный сейф для замка

    // Синхронизация по монитору объекта 'this' (конкретной конторы)
    public synchronized void increment() {
        count++; // Зашли, сделали дело, вышли, сняли "ЗАНЯТО"
    }

    // Синхронизация по монитору класса Counter.class (чертёж завода)
    public static synchronized void staticMethod() {
        // ...
    }

    // Синхронизация по произвольному объекту (нашему личному сейфу)
    public void decrement() {
        synchronized (customLock) { // Замок вешаем именно на customLock, а не на всю дверь
            count--;
        }
    }
}

И главное, блядь, запомни, а то пидарасы налетят: Чтобы эта вся хуйня работала и потоки реально ждали друг друга, а не лезли одновременно в одну дырку, они все должны договориться и использовать один и тот же объект-монитор! Это как если у вас один сортир на всех, а табличка «ЗАНЯТО» одна. Если один будет вешать табличку на дверь, а другой — на унитаз, то доверия ебать ноль, и в итоге все обосрутся.