C ++ 17 shared_mutex: зачем читать блокировку даже необходимо для чтения потоков [duplicate]

Примером этого исключаемого исключения является: Когда вы пытаетесь проверить что-то, это null.

Например:

string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)

if (testString.Length == 0) // Throws a nullreferenceexception
{
    //Do something
} 

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

По сравнению с ArgumentNullException, которое обычно выбрано как защитная мера, если метод ожидает, что то, что происходит

Дополнительная информация находится в C # NullReferenceException и Null Parameter .

33
задан Matthew Murdoch 6 October 2009 в 14:50
поделиться

6 ответов

Доступ к перечислению (чтение или запись) должен быть защищен.

Другое дело: если конфликт потоков меньше, а потоки принадлежат одному и тому же процессу, то критический раздел будет лучше, чем мьютекс.

0
ответ дан aJ. 1 September 2018 в 09:50
поделиться

Вообще говоря, вы этого не делаете, если ваша переменная объявлена ​​с помощью «volatile». И ТОЛЬКО, если это единственная переменная - иначе вы должны быть очень осторожны в возможных гонках.

0
ответ дан EFraim 1 September 2018 в 09:50
поделиться
  • 1
    Почему вы думаете, что нестабильные вещи? – jalf 13 October 2009 в 15:34
  • 2
    @jalf: volatile сообщает компилятору, что он не выполняет оптимизации, которые могут привести к тому, что ваш код увидит устаревшую копию переменной. – Stephen C 13 October 2009 в 15:52
  • 3
    Но речь шла не о несвежих экземплярах. Даже если переменная нестабильна, она будет записана раньше или позже. Он будет атомарным независимо от волатильности, а volatile не предотвращает переупорядочение загрузки / хранения. Так что волатильность на самом деле не покупает вам ничего в этом случае. Он не решает проблему, которая требует решения, и она решает проблему, которая была бы решена в любом случае. – jalf 13 October 2009 в 16:16
  • 4
    @jalf: Ваш рано или поздно может быть бесконечным в случае жесткой петли – EFraim 16 October 2009 в 13:33
  • 5
    да, поэтому правильное решение должно использовать барьер памяти, а не изменчивый. Волатильность в основном бесполезна в контексте многопоточности. Он замедляет ваш код, не предоставляя вам гарантии need . – jalf 16 October 2009 в 14:39

У вас есть два потока, они обмениваются информацией, да вам нужен мьютекс, и вам, вероятно, также потребуется условное ожидание.

В вашем примере (compare state_ == ESTABLISHED) указывает, что поток # 2 ждет для потока # 1, чтобы инициировать соединение / состояние. Без мьютекса или условных выражений / событий поток # 2 должен постоянно отслеживать состояние.

Потоки используются для повышения производительности (или улучшения реагирования), опрос обычно приводит к снижению производительности, либо потребляя много CPU или путем введения латентного за счет интервала опроса.

9
ответ дан Ernelli 1 September 2018 в 09:50
поделиться
  • 1
    +1 для предложения условных переменных. Из его звуков он имеет поток, который должен реагировать на изменение состояния другим изменением. Если в этом случае условные переменные гораздо более приемлемы. – Falaina 6 October 2009 в 16:37
  • 2
    @Ermelli, мы все еще нуждаемся в мьютексе, если мы хотим использовать цикл ожидания занятости в любом случае (потому что цикл мог бы сделать что-то еще между тем) – Nick 7 January 2017 в 17:24

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

wikipedia codeproject

0
ответ дан geva30 1 September 2018 в 09:50
поделиться

Это зависит.

Язык C ++ ничего не говорит о потоках или атомарности.

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

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

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

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

14
ответ дан jalf 1 September 2018 в 09:50
поделиться
  • 1
    Если вы не укажете волатиль, чтение (или запись) может быть выполнено never . Рано или поздно не достаточно. – EFraim 16 October 2009 в 13:34
  • 2
    Но даже с изменчивым процессором или компилятором можно переупорядочить записи, делая их бессмысленными. Правильное решение - это барьер памяти, а затем волатильность - это просто ненужная деоптимизация. – jalf 16 October 2009 в 14:34
  • 3
    @jalf: Нет, если вам нужен только один флаг. Прочтите вопрос еще раз. – EFraim 17 October 2009 в 17:14
  • 4
    И, вероятно, такие решения, как вы предлагаете, приводят к большей части раздутого кода. Нет, вам НЕ нужен барьер для одного флага – EFraim 17 October 2009 в 17:15
  • 5
    Но если флажок проверяется, чтобы определить следующий шаг в его приложении, либо (а) ему нужно поделиться некоторыми другими данными между потоками. (б) проверка флага не имеет смысла, и он может выполнять следующие шаги всегда. Предполагая, что (а) - это сценарий, «другие данные» может не быть готовой только потому, что установлена ​​переменная флага. Предполагая, что это из-за того, что флаг является вероятным подозреваемым при запуске-в-debug-crashes-in-release-build. – peter karasev 13 December 2012 в 09:48

Да. Если thread a читает переменную, а поток b записывает ее, вы можете прочитать неопределенное значение. Операция чтения и записи не является атомарной, особенно в многопроцессорной системе.

3
ответ дан Jeff Ober 1 September 2018 в 09:50
поделиться
  • 1
    в то время как поток записи выполняет (fetch- & gt; write- & gt; store). Я не вижу, когда в середине те, кто читает, получают неопределенное значение, как предыдущее, так и более позднее, но никогда не определяемое. – Arkaitz Jimenez 6 October 2009 в 13:23
  • 2
    Принимая во внимание значения перечисления, которые читаются в одной инструкции. – Arkaitz Jimenez 6 October 2009 в 13:26
  • 3
    @Arkaitz: неопределенное было, вероятно, неправильным словом. Но архитектуры CPU / памяти становятся все более сложными с добавленными уровнями кешей, увеличенными задержками и т. Д. Ответ прост: Скажите Нет! для блокировки обмена данными. Даже эксперты совершают много ошибок в этой области. – sellibitze 6 October 2009 в 14:21
Другие вопросы по тегам:

Похожие вопросы: