Неоднозначность в документации по потокам в C # - PullRequest
0 голосов
/ 03 июля 2011

Читая превосходную книгу Джо Албахари "Threading in C #", я наткнулся на следующее неоднозначное предложение:

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

(Вы можете найти предложение на этой странице ; просто найдите «неопределенность», чтобы быстро перейти к соответствующему разделу.)

Я хочу использовать ConcurrentDictionary для реализации определенных потоковобезопасных структур данных. Указывает ли абзац, что ConcurrentDictionary не гарантирует поточно-ориентированные записи в мою структуру данных? Может ли кто-нибудь предоставить контрпример, показывающий потокобезопасный тип, который на самом деле не обеспечивает безопасность потока?

Заранее спасибо за помощь.

Ответы [ 8 ]

8 голосов
/ 03 июля 2011

Проще говоря, потокобезопасный список или словарь является хорошим примером; наличие каждой индивидуальной безопасной работы потока не всегда достаточно - например, «проверить, пуст ли список; если это так, добавить элемент» - даже если все потокобезопасно, вы не можете сделать :

if(list.Count == 0) list.Add(foo);

как это может измениться между двумя. Вам нужно синхронизировать тест и изменения.

4 голосов
/ 03 июля 2011

Некоторое время назад занимался поиском, чтобы исправить проблему с поточностью, с которой я столкнулся, и наткнулся на эту страницу:

http://www.albahari.com/threading/part2.aspx#_Thread_Safety

В частности, раздел «Блокировка вокруг потоковых объектов»

Со страницы:

Иногда вам также нужно заблокировать доступ к объектам, безопасным для потоков. Чтобы проиллюстрировать это, представьте, что класс List платформы Framework действительно является поточно-ориентированным, и мы хотим добавить элемент в список:

if (!_list.Contains (newItem)) _list.Add (newItem);

Независимо от того, был ли список поточно-ориентированным, это утверждение, безусловно, не является!

4 голосов
/ 03 июля 2011

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

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

2 голосов
/ 03 июля 2011

Я думаю, он имеет в виду, что простое использование ConcurrentDictionary вместо Dictionary не сделает программу поточно-ориентированной.Таким образом, если у вас есть не поточнобезопасная программа, поиск и замена не помогут;аналогично, добавление SynchronizedAttribute везде не будет работать, как волшебная волшебная пыль.Это особенно верно в отношении коллекций, где итерация всегда является проблемой [1].

С другой стороны, если вы реструктурируете не поточно-ориентированную программу в более поточно-ориентированный дизайн, то вы частоне нужны потокобезопасные структуры данных.Один из популярных подходов заключается в переопределении программы в терминах «действующих лиц», которые отправляют «сообщения» друг другу - кроме единой очереди сообщений типа «производитель / потребитель», каждый участник может оставаться в одиночестве и не должен использовать потокобезопасные данные.внутренние структуры.

[1] Первый выпуск коллекций BCL включал некоторые «поточно-безопасные» коллекции, которые просто были не поточно-безопасными во время итераций.Коллекции Concurrent во время итерации являются потокобезопасными, но итерируются одновременно с изменениями других потоков.Другие библиотеки коллекций допускают «моментальные снимки», которые затем можно повторять, игнорируя изменения из других потоков.

1 голос
/ 03 июля 2011

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

1 голос
/ 03 июля 2011

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

При работе сВ этой ситуации вы, вероятно, сделаете всю эту операцию атомарной и, следовательно, поточно-ориентированной, что сделает поточно-ориентированный доступ к отдельным элементам неактуальным.

Если не означает, что ваш ConcurrentDictionary будет вести себянебезопасным способом.

0 голосов
/ 04 июля 2011

Этот параграф говорит мне, что ConcurrentDictionary не гарантия потокобезопасности пишет в мой структура данных?

Нет, это не то, что имеет в виду Джо Албахари. ConcurrentDictionary всегда будет поддерживать согласованное состояние посредством одновременной записи из нескольких потоков. Другой поток никогда не увидит структуру данных в несогласованном состоянии.

Может кто-нибудь предоставить контрпример, который показывает потокобезопасный тип фактически не в состоянии обеспечить безопасность потока?

Однако в многопоточной среде может произойти сбой серии операций чтения и записи из поточно-безопасного типа.

void ExecutedByMultipleThreads(ConcurrentQueue<object> queue)
{
  object value;
  if (!queue.IsEmpty)
  {
    queue.TryDequeue(out value);
    Console.WriteLine(value.GetHashCode());
  }
}

Очевидно, что ConcurrentQueue является потокобезопасным типом, но эта программа все равно может завершиться с ошибкой NullReferenceException, если другой поток снял последний элемент с очереди между методами IsEmpty и TryDequeue. Сама структура данных все еще обеспечивает свою гарантию безопасности потока, оставаясь в согласованном состоянии, но программа не является поточно-ориентированной, так как предположения о безопасности потока в целом неверны. В этом случае это программа , которая неверна; не структура данных.

0 голосов
/ 03 июля 2011

Рой,

Я полагаю, вы "перечитываете" слишком сжатое предложение ... Я интерпретирую это предложение как означающее две вещи:

  1. " Просто использование потоковых структур данных не означает, что ваша программа правильно обрабатывает многопоточность ... и даже больше, чем наличие потоковых структур данных по своей сути делает вашу программу многопоточной ";и затем он продолжает
  2. «Если вы не готовы использовать« трудные дворы »(это часто требует очень точного понимания довольно сложных сценариев), чтобы ваша ВСЕ программа правильно обрабатывала потоки,использование поточно-ориентированной структуры данных, по сути, пустая трата тактов.

Ergo: Многопоточность довольно сложна, использование соответствующих готовых структур данных является важной частью любого решения., но это, конечно, НЕ целое решение ... и если вы не готовы продумать это (т.е. выполнить домашнее задание по синхронизации), вы просто шутите, что структура данных каким-то волшебным образом "исправит" вашупрограмма.

Я знаю, что это звучит "немного резко", но я понимаю, что многие новички действительно разочаровываются, когда обнаруживают, что программирование (тем не менее, в этот просвещенный век анимированных иконок и художников с графическим интерфейсом) требует глубокогоМысль. Кто бы это понял?!?!

Приветствия. Кит.

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