Почему синхронизированный не может синхронизировать поток? - PullRequest
0 голосов
/ 26 января 2020

Я установил значение флага, но результат не является альтернативой «добавить» и «суб». Почему? Когда я смотрю на результат, он дважды выполнил метод 'sub'. Но когда метод 'sub' завершится, значение флага будет установлено как 'false'. Но в результате он дважды печатал «subxxxxx».

class Resource {
    private boolean flag = true;
    private int num = 0;

// At here I have declared an add()
    public synchronized void add() throws InterruptedException {
        if (this.flag == false) {
            super.wait();
        }
        Thread.sleep(100);
        this.num++;
        System.out.println("addition:"+Thread.currentThread().getName() + this.num);
        this.flag = false;
        super.notifyAll();
    }

// At here I have declared an sub()
    public synchronized void sub() throws InterruptedException {
        if (this.flag == true) {
            super.wait();
        }
        Thread.sleep(200);
        this.num--;
        System.out.println("subtraction:"+Thread.currentThread().getName() + this.num);
        this.flag = true;
        super.notifyAll();
    }
}

/*
* I will test it with multiple threads. For example:
*new Thread(ad, "add").start();
*new Thread(ad, "add").start();
*new Thread(sub, "sub").start();
*new Thread(sub, "sub").start();
*When threads start. it will execute alternately. For example:
Thread add:0
Thread sub:-1
Thread add:0
Thread sub:-1
Thread add:0
Thread sub:-1
Thread add:0
Thread sub:-1
But the result is like this:
Thread add:0
Thread sub:-1
Thread sub:-2
Thread add:-1
Thread sub:-3
Thread sub:-4
Why?Why?Why?
*/
        new Thread(ad, "add").start();
        new Thread(ad, "add").start();
        new Thread(sub, "sub").start();
        new Thread(sub, "sub").start();
    }
}

1 Ответ

0 голосов
/ 26 января 2020

Похоже, вы предполагаете, что когда ваш wait() вызов завершится, flag изменился на то, что вы хотели получить до того, как позвонили wait(). Такой гарантии нет, тем более что у вас более двух потоков. Вы должны проверить, если вам нужно продолжать ждать. Также смотрите Дождитесь, пока логическое значение не изменит свое состояние

Но в целом эти конструкции слишком низкоуровневые, чтобы их можно было использовать (если вы не хотите изучать все детали), и вам следует взглянуть на пакет concurreny utils для более простых конструкций более высокого уровня (таких как очереди, защелки, условия).

...