Как бороться с параллелизмом, прежде чем начать кодирование - PullRequest
16 голосов
/ 30 января 2010

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

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

Говоря в самых общих чертах, какие приемы мне следует использовать при принятии решения о том, как мое приложение должно "течь", когда все мои потоки не завязаны в узел?

Ответы [ 9 ]

6 голосов
/ 30 января 2010

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

"Все проблемы параллелизма сводятся к координация доступа к изменяемому состоянию. Чем менее изменчивое состояние, тем легче заключается в обеспечении безопасности потока. " - Java параллелизм на практике

Итак, вопрос, который вы должны задать себе:

  • Что такое присущие общие данные, которые понадобятся моему приложению?
  • Когда поток может работать с снимком данных, то есть мгновенно работать с клоном общих данных?
  • Могу ли я определить известный шаблон и использовать абстракцию более высокого уровня, а не блокировки низкого уровня и координацию потоков, например, очереди, исполнитель и т. д.?
  • Подумайте о глобальной схеме блокировки, чтобы избежать тупика и иметь последовательные захваты блокировок

Самый простой подход к управлению общим состоянием - это сериализация каждого действия. Однако этот грубый подход приводит к высокой конкуренции за блокировку и низкой производительности. Управление параллелизмом можно рассматривать как упражнение по оптимизации, в котором вы пытаетесь уменьшить конкуренцию. Итак, следующие вопросы:

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

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

  • Где я могу ослабить несколько ограничений и признать, что иногда вещи не будут на 100% правильными (например, счетчик)?
  • Могу ли я быть оптимистом и иметь дело с конфликтом только тогда, когда происходят параллельные изменения (например, с использованием метки времени и логики повторения - это то, что делает ТМ)?

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

5 голосов
/ 30 января 2010

Читайте о параллелизме или, еще лучше, изучите курс для выпускников по параллельному программированию, если вы еще учитесь в колледже. См. Учебные руководства по Java: урок: параллелизм . Одна известная книга по параллелизму Java - Параллелизм Java на практике . Java имеет так много встроенных в структуру для решения проблем параллелизма, включая одновременные коллекции и synchronized методы .

Практический параллелизм Java http://ecx.images -amazon.com / images / I / 51Hx% 2Bg4Q6QL._BO2,204,203,200-76_AA240_SH20_OU01_.jpg

5 голосов
/ 30 января 2010

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

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

Edit:

Вот несколько ссылок на некоторые библиотеки, которые вы могли бы использовать в вашем следующем проекте. Существует Deuce STM , который, как следует из названия, является реализацией STM для Java. Тогда есть ActorFoundry , который, как следует из названия, является моделью Actor для Java. Тем не менее, я не могу не сделать плагин для Scala со встроенной моделью Actor.

2 голосов
/ 30 января 2010

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

List<Item> items = new ArrayList<Item>();

//... some code adding items to the list

for (Item item : items) {
    if(item.isTheOneIWantToRemove()) {
        items.remove(item); //This will result in a ConcurrentModificationException
    }
}

Изменение цикла for на цикл с итератором или увеличение значения индекса решает проблему:

for (Iterator<String> it = items.iterator(); it.hasNext();) {
    if(item.isTheOneIWantToRemove()) {
        it.remove(); //No exception thrown
    }
}

или

for (int i = 0; i < items.size(); i++) {
    if(item.isTheOneIWantToRemove()) {
        items.remove(items.get(i)); //No exception thrown
    }
}
2 голосов
/ 30 января 2010

Чем меньше у вас потоков, тем меньше у них общего состояния и чем проще шаблон взаимодействия в этом общем состоянии, тем проще будет ваша жизнь.

Вы говорите, что списки генерируют исключение ConcurrentModificationException. Я полагаю, что к вашим спискам обращаются отдельные темы. Итак, первое, что вы должны спросить себя, является ли это необходимым. Разве второй поток не может работать с копией списка?

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

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

1 голос
/ 30 января 2010

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

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

0 голосов
/ 19 июля 2010

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

http://javatip.com/2010/07/core-java/concurrency/thread-safe-without-synchronization

0 голосов
/ 30 января 2010
  1. Попробуйте использовать коллекции из пакета java.util.concurrent или, что еще лучше, коллекции из Google Collections.
  2. Читать об использовании синхронизированных блоков
0 голосов
/ 30 января 2010

Это зависит от того, что делают ваши темы.Обычно программы имеют основной поток, который выполняет мыслительный и рабочий потоки для выполнения параллельных задач (таймеры, обработка длинных вычислений в графическом интерфейсе и т. Д.). Но ваше приложение может отличаться - это зависит от вашего дизайна.Для чего вы используете темы?Какие блокировки вы используете для защиты общих структур данных?Если вы используете несколько блокировок, есть ли у вас один порядок блокировки, чтобы предотвратить взаимные блокировки?

...