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

У меня есть синхронизированный метод в классе.Код в предложении try вызывает notifyAll() и wait().Когда я запускаю код, все потоки работают в соответствии с выводом.Но оказывается, что только два потока вызывают метод по очереди.Это ужасно.

Я пытался написать синхронизированный блок в цикле while несинхронизированного метода, и он работает хорошо.Обратите внимание, что всего 5 потоков.

Вот синхронизированный метод:

private synchronized void sell() {
        while (ticketsLeft > 0) {
            try {
                    System.out.println(Thread.currentThread().getName() + "__________" + (ticketsLeft--));
                    this.notifyAll();
                    Thread.sleep(10);
                    this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.exit(0);
    }

Я также попытался поместить цикл while в синхронизированный блок, произошло то же самое.

private void sell() {
        synchronized (this) {
            while (ticketsLeft > 0) {
                try {
                    System.out.println(Thread.currentThread().getName() + "__________" + (ticketsLeft--));
                    this.notifyAll();
                    Thread.sleep(10);
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.exit(0);
        }
    }

И это работает так, поток 3 и 4 по очереди вызывает метод:

5__________100
1__________99
2__________98
3__________97
4__________96
3__________95
4__________94
3__________93
4__________92
3__________91
4__________90
3__________89
4__________88
3__________87
4__________86
3__________85
4__________84
3__________83
4__________82
3__________81
4__________80

С синхронизированным блоком в цикле while внутри несинхронизированного метода:

    private void sell() {
        while (ticketsLeft > 0) {
            try {
                synchronized (this) {
                    System.out.println(Thread.currentThread().getName() + "__________" + (ticketsLeft--));
                    this.notifyAll();
                    Thread.sleep(10);
                    this.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.exit(0);
    }

И все работает, как я и ожидал:

5__________100
3__________99
2__________98
1__________97
4__________96
1__________95
2__________94
3__________93
1__________92
4__________91
3__________90
2__________89
5__________88
2__________87
3__________86
4__________85
1__________84
3__________83
2__________82
5__________81
3__________80

Спасибо, ребята, что прочитали этот вопрос.Мне жаль, что у меня недостаточно репутации для публикации изображений.Буду признателен, если у кого-то есть идеи по этому поводу.

1 Ответ

0 голосов
/ 09 мая 2019

Недостаточно информации, чтобы правильно ответить на вопрос. Но я думаю, что это как-то связано с тем, что цикл while находится вне синхронизированного блока во 2-м случае, и это первый случай цикла while внутри синхронизированного метода.

Все потоки будут ждать внутри цикла while во втором методе, но для первого они будут ждать вне цикла while.

Примечание. И синхронизированный метод, и синхронизированный метод блокируют текущий экземпляр класса, в котором работают ваши потоки.

Надеюсь, это поможет! : -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...