Почему этот простой пример блока синхронизированного кода Java дает мне различный вывод в зависимости от того, на каком объекте я блокируюсь?

1

Хорошо, поэтому я пытаюсь изучить многопоточность. Я читаю книгу, и я столкнулся с этим примером для синхронизированных блоков кода:

class CallMe {
    void call(String msg) {
        System.out.print("[" + msg);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            System.out.println("Interrupted");
        }
        System.out.println("]");
    }
}

class Caller implements Runnable {

    String msg;
    CallMe target;
    Thread t;

    public Caller(CallMe target, String msg) {
        this.target = target;
        this.msg = msg;
        t = new Thread( this );
        t.start();
    }

    public void run() { 
        synchronized (target) {
            target.call(msg);
        }
    }
}

public class Scrap {
    public static void main(String[] args) {
        CallMe target = new CallMe();
        Caller ob1 = new Caller( target, "Hello");
        Caller ob2 = new Caller( target, "Synchronized" );
        Caller ob3 = new Caller( target, "World");

        try {
            ob1.t.join();
            ob2.t.join();
            ob3.t.join();
        } catch (Exception e) {
            System.out.println("Interrupted");
        }
    }
}

Я получил следующий результат:

[Hello]
[World]
[Synchronized]

Затем, поскольку я сделал несколько учебников в Интернете, я знаю, что это хороший стиль (или ему сказали) создать экземпляр Object только для блокировки. Итак, я сделал это, и класс Caller стал:

class Caller implements Runnable {
    String msg;
    CallMe target;
    Thread t;

    private Object lock = new Object();

    public Caller(CallMe target, String msg) {
        this.target = target;
        this.msg = msg;
        t = new Thread( this );
        t.start();
    }

    public void run() {
        synchronized (lock) {
            target.call(msg);
        }
    }
}

Я был немного удивлен, когда получил это как результат:

[Synchronized[Hello[World]
]
]

Конечно, это выводится, когда происходит чередование, и это неверно. Мой вопрос, почему это произошло? Я думал, что создание Object блокировки даст мне те же результаты. Почему он (или почему бы ему) не дал мне такой же результат? Я думал, что создание экземпляра Object будет хорошим стилем и будет работать одинаково в этом случае, и, честно говоря, я не понимаю, почему это будет другая блокировка на "target" и "lock". Я предполагаю, что я хочу спросить, почему блокировка на одном определенном элементе в этом случае заставляет программу быть правильной и блокировать с другой, делает ее неправильной?

Теги:
multithreading
locking

1 ответ

2
Лучший ответ

Каждый экземпляр Caller блокирует другой экземпляр lock. Я думаю, вам нужно synchronize с общими экземплярами. Создание lock в static члене будет иметь один и тот же экземпляр для всех потоков.

  • 1
    Скажите «статический» вместо общего, и я думаю, что вы выиграете этот вопрос. :)
  • 1
    @mttdbrd Не делайте вещи static чтобы вы могли ими поделиться. Вы можете передать тот же аргумент, если вам нужно.
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню