Следует ли блокировать ресурсы при чтении значений?

При выполнении синхронизации потоков в C# должен ли я также блокировать объект, когда я читаю значение или просто меняю его?

например, у меня есть объект Queue <T>. Должен ли я просто заблокировать его при выполнении постановки в очередь и удаление, или я должен также заблокировать его при проверке таких значений, как счетчик?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
1 136
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

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

CLR гарантирует атомарное чтение значений вплоть до ширины процессора. Так что, если вы работаете на 32-битной системе, чтение int будет атомарным. Если вы работаете на 64-битной машине, чтение long будет атомарным. Ergo, если Count - это Int32, блокировка не требуется.

Эта почта имеет отношение к вашему вопросу.

Чтение int может быть атомарным, но вычисление счетчика не обязательно может быть атомарным. Это не просто чтение int. Помимо прочего, для этого требуется вызов функции.

mmx 10.01.2009 18:47

А Count, скорее всего, является свойством, которое соответствует неявному вызову функции.

Hosam Aly 10.01.2009 18:50

Подсчет вычислений? Из собственности? Это серьезно нарушило бы мои ожидания относительно поведения собственности. Ожидание (которое в данном случае верно) состоит в том, что доступ к свойству просто возвращает значение поля.

Kent Boogaart 10.01.2009 18:56

По крайней мере, для List <T> счетчик рассчитывается при каждом доступе! Возможно Reflector раскроет подробности о Queue <T> ...

Florian Greinacher 10.01.2009 19:12

Если вы не заблокируете его, вы можете получить более старое значение. Может возникнуть состояние гонки, при котором выполняется операция записи с изменением Count, но при изменении вы получите значение перед. Например, если в очереди только один элемент, и поток вызывает удаление из очереди, другой поток может прочитать счетчик, найти его по-прежнему равным 1 и снова вызвать удаление из очереди. Второй вызов не будет выполнен до тех пор, пока не будет предоставлена ​​блокировка, но в это время очередь фактически будет пустой.

Ответ принят как подходящий

Из MSDN:

A Queue<(Of <(T>)>) can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.

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

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

if (queue.Count > 0)
    queue.Dequeue();

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

mmx 10.01.2009 18:50

Другие вопросы по теме