Строго говоря, что вы можете безопасно делать с делегатом в нескольких потоках? - PullRequest
5 голосов
/ 27 марта 2012

Согласно документации System.MulticastDelegate :

Thread Safety

Любые открытые статические (Shared в Visual Basic) члены этого типа являются потокобезопасными. Ни один из членов экземпляра не гарантированно является потокобезопасным.

То же утверждение существует в документации для System.Delegate.

Теперь у делегатов есть неизменный API, но, как объясняет Эрик Липперт , «ошибочно полагать, что только потому, что структура данных не допускает никакого способа для , вы меняете ее содержимое, ее реализация должна быть поточно-безопасной! "

Некоторые механизмы для создания новых делегатов из существующих делегатов являются статическими методами: Delegate.Combine и Delegate.Remove. Похоже, что они потокобезопасны. Имея многоадресных делегатов A, B и C, я могу смело комбинировать A и B, чтобы создать D в одном потоке, а B и C создать E в другом.

Но вызов делегата не является статическим методом. Означает ли это, что технически мой код может сломаться, если я разделю делегат между потоками и вызову его в обоих, или если я вызову делегат в одном потоке, комбинируя его с другим в другом потоке? Может ли реализация, соответствующая стандартам, MulticastDelegate привести к неопределенному поведению в таком сценарии? Гарантируется, что делегат, возвращенный Combine или Remove, не делит скрытое изменяемое состояние с каким-либо другим делегатом?

Обратите внимание, что я спрашиваю о том, что стандарт гарантирует , а не о текущем поведении компиляторов C # и CIL JIT. Экспериментально я могу определить, что это действительно кажется безопасным, используя каждый из .NET и Mono на доступных мне архитектурах, но я не вижу, что определяет или гарантирует это поведение.

Ответы [ 2 ]

1 голос
/ 21 мая 2012

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

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

Безопасность потока при наличии записи не может быть принята так просто . Я не знаю ответа здесь. В спецификации ничего не говорится о потоках. Может быть невозможно изменить значения делегата, но они могут восприниматься как измененные под влиянием потоков. Кто знает. Мы говорим строго, в конце концов :)

0 голосов
/ 21 мая 2012

Хотя я не могу найти никаких ограничений реализации, я считаю, что это подразумевается.

См. Раздел 14.5.10.3 в http://www.ecma -international.org / публикации / файлы / ECMA-ST / Ecma-334.pdf

"Метод и объект, на которые ссылается делегат, определяются, когда создается экземпляр делегата, и затем остаются постоянными в течение всего времени жизни делегата. Другими словами, невозможно изменить целевой метод или объект делегата после того, как он был создан. [Примечание: Помните, что когда два делегата объединены или один удален из другого, появляется новый делегат; ни один из существующих делегатов не изменил его содержание. end note] "

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

...