Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация 
:(
    Опции темы
Platon
Дата 6.1.2011, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Здравствуйте, уважаемые.

Давно я не занимался потоками, освежить память своими силами не удалось. Проблема возникла в следующем коде:

Код


    private final Object block = new Object();

    private int threads = 0;

    public void process() throws InterruptedException {
        synchronized (block) {
            while (threads > 0) {
                System.out.println(Thread.currentThread().getName() + " Threads waiting: " + threads);
                block.wait();
                System.out.println(Thread.currentThread().getName() + " awake");
            }
            threads++;
        }
        // кое-какая дополнительная дрёма без синхронизации
        System.out.println(Thread.currentThread().getName() + " processing");
    }

    public void jobDone() {
        synchronized (block) {
            threads--;
            System.out.println(Thread.currentThread().getName() + " Notifying. Threads amount " + threads);
            block.notify();
        }
    }


запускаю таким образом:

Код

for (int i = 0; i < 10; i++)
            new Thread(new Runnable() {
                public void run() {
                    Thread t = Thread.currentThread();
                    try {
                        for (int i = 0; i < 100; i++) {
                            manager.process();
                            System.out.println(t.getName() + " sleep for 2 seconds");
                            Thread.sleep(2000);
                            manager.jobDone();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();



Картина на выходе

Цитата

Thread-0 processing
Thread-1 Threads waiting: 1
Thread-0 sleep for 2 seconds
Thread-4 Threads waiting: 1
Thread-3 Threads waiting: 1
Thread-2 Threads waiting: 1
Thread-5 Threads waiting: 1
Thread-6 Threads waiting: 1
Thread-8 Threads waiting: 1
Thread-7 Threads waiting: 1
Thread-9 Threads waiting: 1
Thread-0 Notifying. Threads amount 0
Thread-0 processing
Thread-0 sleep for 2 seconds
Thread-1 awake
Thread-1 Threads waiting: 1

Thread-0 Notifying. Threads amount 0
Thread-0 processing
Thread-0 sleep for 2 seconds
Thread-4 awake
Thread-4 Threads waiting: 1
Thread-0 Notifying. Threads amount 0
Thread-0 processing
Thread-0 sleep for 2 seconds
Thread-3 awake
Thread-3 Threads waiting: 1
Thread-0 Notifying. Threads amount 0
Thread-0 processing
Thread-0 sleep for 2 seconds
Thread-2 awake
Thread-2 Threads waiting: 1
Thread-0 Notifying. Threads amount 0
Thread-0 processing
Thread-0 sleep for 2 seconds
Thread-5 awake
Thread-5 Threads waiting: 1


Выделил характерную ситуацию. Поток-0 успевает сообщить о том, что собирается освободить блок в методе jobDone() и успевает сразу занять его в методе process(), благополучно преодолеть его, плюсануть число активных потоков и дальше идёт процесс. В чём дело, КЭП?
PM MAIL ICQ   Вверх
Platon
Дата 6.1.2011, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Маленькое уточнение, если поставить задержку после метода manager.jobDone(); то потоки успевают перехватить монитор.
PM MAIL ICQ   Вверх
_sten_
Дата 6.1.2011, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 184
Регистрация: 29.9.2006

Репутация: нет
Всего: 3



а можно поподробней что именно происходит не так как ожидалось?
--------------------
WARNING: Condition 'to_be || !to_be' is always 'true' !
PM MAIL ICQ   Вверх
Platon
Дата 6.1.2011, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Цитата
Поток-0 успевает сообщить о том, что собирается освободить блок в методе jobDone() и успевает сразу занять его в методе process(), благополучно преодолеть его, плюсануть число активных потоков и дальше идёт процесс.


Хотелось бы, чтобы не только один поток выполнял всю работу. Возможно, всё идёт так как надо, но складывается впечатление, что код написан неверно. Я ожидал, что потоки будут поочерёдно выполнять работу. Выйти из метода jobDone, успеть войти в метод process и захватить монитор... Это похоже на ситуацию, когда футболист пинает мяч, бежит за ним, опережает его и принимает.
PM MAIL ICQ   Вверх
priam220
Дата 10.1.2011, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 4.6.2010

Репутация: 7
Всего: 8



У тебя получается, что один какой-то процесс привелегированный, потому как threads для него равен нулю и он в цикл с wait не попадает и обгоняет все остальные в несколько раз из за этого. 
Мне кажется, это вполне нормально, в том смысле что какая разница какой поток будет выполнять работу, этот или тот. Если этот свободен - пусть делает. Быстрее ведь не будет, наоборот. 
Если принципиально надо что бы они все трудились, - то надо менять условие в process() while. 
Но в реалии код обрастет мясом, и потоки будут успевать просыпаться и занимать очередь у монитора. Так что мое мнение - все ок. 
Кстати notify не гарантирует, что будет выбран другой поток, так что в любом случае, такое поведение нельзя будет исключить.



Это сообщение отредактировал(а) priam220 - 10.1.2011, 22:08
PM MAIL   Вверх
priam220
Дата 10.1.2011, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 4.6.2010

Репутация: 7
Всего: 8



Platon,  кстати а зачем вы используете while? Мне кажется его лучше заменить на if. И картина сразу меняется в лучшую сторону:
Код

Thread-0 Notifying. Threads amount 0
Thread-1 awake
Thread-1 processing
Thread-1 sleep for 2 seconds
Thread-0 Threads waiting: 1
Thread-1 Notifying. Threads amount 0
Thread-2 awake
Thread-2 processing
Thread-2 sleep for 2 seconds
Thread-1 Threads waiting: 1
Thread-2 Notifying. Threads amount 0
Thread-3 awake
Thread-3 processing
Thread-3 sleep for 2 seconds
Thread-2 Threads waiting: 1
Thread-3 Notifying. Threads amount 0
Thread-3 processing
Thread-3 sleep for 2 seconds
Thread-4 awake
Thread-4 processing
Thread-4 sleep for 2 seconds
Thread-3 Notifying. Threads amount 1
Thread-3 Threads waiting: 1
Thread-4 Notifying. Threads amount 0

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0833 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.