Как избежать изменяемого состояния (при многопоточности) - PullRequest
3 голосов
/ 29 июня 2009

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

Например. У вас есть большой список объектов, каждый из которых содержит довольно много свойств; другими словами: большая структура данных. Предположим, у вас есть несколько потоков, и все они должны получить доступ к списку и изменить его. Как это можно сделать без общей памяти без необходимости кэшировать всю структуру данных в каждом из потоков?

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

Ответы [ 6 ]

2 голосов
/ 29 июня 2009

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

http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx

2 голосов
/ 29 июня 2009

Не каждый алгоритм может быть успешно распараллелен.

Если ваша программа не имеет «параллельной структуры», то вы довольно обречены на использование блокировок и разделяемых, изменяемых структур.

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

Итак: думайте с точки зрения структуры алгоритма, а не с точки зрения свойств используемой структуры данных.

1 голос
/ 29 июня 2009

Если вам действительно нужно обновить структуру, то один способ сделать это - создать отдельный рабочий поток, который получает запросы на обновление из фиксированной области, защищенной мьютексом.

Если вы умны, вы можете обновить структуру на месте, не влияя на любое «чтение» потоки (например, если вы добавляете в конец массива, вы делаете всю работу по добавлению новой структуры, но только в качестве самой последней инструкции вы увеличиваете счетчик NoOfMembers - читающие потоки не должны видеть новую запись, пока вы не сделаете это - или - организовать ваши данные как массив ссылок на структуры - когда вы хотите обновить структуру, вы копируете текущий элемент, обновляете его, а затем, как последняя операция, заменяете ссылку в массиве)

Тогда другим потокам нужно проверять только один простой мьютекс «update in progess» только тогда, когда они активно хотят обновить.

1 голос
/ 29 июня 2009

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

1 голос
/ 29 июня 2009

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

Если у вас есть большой объем данных, которые необходимо изменить, вы, возможно, не сможете избежать изменяемого состояния. Альтернативой может быть разделение данных на блоки, каждый из которых передается потоку для манипуляции. Блок может быть обработан и затем передан обратно, и контроллер может затем выполнить обновления, где это необходимо. В этом сценарии вы удалили изменяемое состояние из потока.

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

1 голос
/ 29 июня 2009

Наверное, первый вопрос: зачем им нужно изменять список? Могут ли они вернуть свои изменения в виде списка изменений, а не вносить изменения в общий список? Могут ли они работать со списком, который выглядит как изменяемая версия исходного списка, но на самом деле является только локально изменяемым? Вы изменяете, какие элементы находятся в списке, или только свойства этих элементов?

Это всего лишь вопросы, а не ответы, но я пытаюсь побудить вас подумать о своей проблеме по-другому. Посмотрите на более широкую картину как на задачу, которую вы хотите достичь, вместо того, чтобы думать о том, как вы решите ее обычным, обязательным и изменчивым образом. Изменение того, как вы думаете о проблемах, очень сложно, но вы можете обнаружить, что вы получаете отличное «ага!» моменты:)

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