Темы зашли в тупик, несмотря на синхронизированное ключевое слово - PullRequest
1 голос
/ 07 июня 2011

Я попытался создать диспетчер событий в Java, который будет отправлять события как потоки. Таким образом, все классы EventListener по существу реализованы классом Runnable. Как и в случае традиционного запуска событий, метод в классе диспетчера событий проходит по списку EventListeners и затем вызывает их метод-обработчик, за исключением того, что на этот раз я вызываю эти обработчики как потоки, помещая слушатели в новый поток (handlerObject). Начните(). Фактическая обработка выполняется в методе run () в EventListener.

Так это выглядит примерно так:

for(EventListener listener : listenerList) {
   if(listener instanceof Runnable)
      new Thread(listener).start();
}

Таким образом, все инструкции для обработки события в слушателе помещены в метод run (), который будет выполняться, когда thread.start ().

Но проблема в том, что потоки часто оказываются в ситуации, когда один из потоков застрял где-то и не смог продолжить. Иногда несколько потоков могут также зависнуть, в то время как некоторым удалось выполнить все инструкции метода run () в слушателе. Я посмотрел вверх, и это звучит как то, что называется тупиком.

Я пытался установить модификатор "synchronized" для всех моих методов, но проблема все еще остается. Я думал, что ключевое слово synchronized просто поставит в очередь все потоки, пытающиеся запустить подобный метод, пока текущий поток, выполняющий метод, не завершится. Но это еще не решает проблему. Почему синхронизация не решает проблему, особенно если она у меня уже есть на всех моих методах, и она должна ставить в очередь любой параллельный доступ, который потенциально может вызвать взаимоблокировку? Я не использовал методы wait () или notify (). Просто простой диспетчер событий, который пытается запустить свой прослушиватель событий как поток.

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

Спасибо за любую помощь.

Ответы [ 4 ]

4 голосов
/ 07 июня 2011

тупик это что-то вроде этого:

А нуждается в железе для изготовления инструментов, просит Б утюг
Б нужны инструменты для изготовления железа, просит А для инструментов

Ни то, ни другое не будет завершено. Тот факт, что вы поместили синхронизированное ключевое слово вокруг них, не гарантирует, что вы столкнетесь с логической невозможностью. Вы должны судить, когда одна вещь сможет двигаться вперед, а когда нет.

1 голос
/ 07 июня 2011

Никогда не добавляйте synchronized ко всем методам, это ничего не решает - вы эффективно сделаете вашу программу однопоточной.

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

К сожалению, без специального кода или понимания фактической синхронизации, происходящей в вашем приложении, единственный совет, который можно дать, - это, в общем, общий характер.

0 голосов
/ 07 июня 2011

Ваша настоящая проблема в том, что вы недостаточно хорошо понимаете параллелизм, чтобы понять, почему ваша программа не работает, не говоря уже о том, как решить эту проблему.(FWIW - добавление synchronized ко всем вашим методам только усугубляет проблему.)

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


@ wheaties имеет микро-объяснение того, что такое тупик, и @matt_b предлагает полезные советы по диагностике тупика.Однако это мало поможет, если вы не знаете правильный способ разработки и написания своего многопоточного кода.

0 голосов
/ 07 июня 2011

Я не знаю, что вы подразумеваете под 'тупик несмотря на синхронизированное ключевое слово'.Ключевое слово synchronized не предотвращает взаимоблокировки.Это может вызвать их, если у вас есть два потока, которые получают блокировки в разных порядках.Решение: не.

...