Поток безопасности ... каков мой "лучший" образ действий? - PullRequest
0 голосов
/ 15 июня 2009

Мне интересно, каков "лучший" способ сделать данные потокобезопасными.

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

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

Ответы [ 4 ]

5 голосов
/ 15 июня 2009

Один из подходов, который не является широко используемым, но вполне обоснованным, состоит в том, чтобы назначить один поток специального назначения для управления каждой «разделяемой» структурой. Этот поток обычно ожидает в очереди (потокобезопасен ;-), например, в Python экземпляр Queue.Queue для рабочих запросов (чтение или изменение общей структуры), включая как те, которые запрашивают ответ (они передадут собственную очередь, в которую ответ будет помещен, когда будет готов), так и те, которые не делают , Этот подход полностью сериализует весь доступ к общему ресурсу, легко переназначает многопроцессную или распределенную архитектуру (почти бездумно, в Python, с multiprocessing ;-), и абсолютно гарантирует надежность и отсутствие взаимоблокировок, а также условия гонки. пока базовый объект очереди хорошо запрограммирован раз и навсегда.

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

OTOH, это может быть чуть-чуть выше, чем тяжелый путь с помощью замков & c; -).

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

Вы могли бы рассмотреть неизменную коллекцию. Очень похоже на то, как строка в .net имеет такие методы, как Replace, Insert и т. Д. Она не изменяет строку, а вместо этого создает новую, коллекцию LinkedList также можно создать неизменной. На самом деле LinkedList на самом деле довольно просто реализовать таким образом по сравнению с некоторыми другими структурами данных коллекции.

Вот ссылка на сообщение в блоге, в котором обсуждаются неизменные коллекции, и ссылка на некоторые реализации в .NET.

http://blogs.msdn.com/jaredpar/archive/2009/04/06/immutable-vs-mutable-collection-performance.aspx

0 голосов
/ 15 июня 2009

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

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

Мое предложение

  1. Начните с глобальной блокировки вашей структуры данных. Профилируйте свою программу, чтобы увидеть, действительно ли это проблема.

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

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

0 голосов
/ 15 июня 2009

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

После этого запомните эмпирические правила:

  • Остерегайтесь всех ваших глобальных переменные / переменные в куче.
  • Убедитесь, что ваши подпрограммы повторный абитуриент.
  • Убедитесь, что доступ к общим данным сериализованная.
  • Убедитесь, что нет никаких косвенных доступ через указатели.

(я уверен, что другие могут добавить больше.)

...