Одно чтение потока, а другое - запись в переменную volitable - thread-safe? - PullRequest
4 голосов
/ 19 июня 2010

В CI есть указатель, который объявлен как volatile и инициализирован нулем.

void* volatile pvoid;

Поток 1 иногда читает значение указателя, чтобы проверить, не является ли оно ненулевым.Поток 1 не будет устанавливать значение указателя.Поток 2 установит значение указателя только один раз.

Я полагаю, что могу обойтись без использования мьютекса или переменной условия.
Есть ли какая-то причина, по которой поток 1 будет читать поврежденное значение или поток 2 будет писать поврежденное значение?

Ответы [ 6 ]

3 голосов
/ 19 июня 2010

Чтобы сделать его потокобезопасным, вы должны делать атомарные операции чтения / записи в переменную, поскольку эта переменная переменная не безопасна во всех ситуациях синхронизации. В Win32 есть функции Interlocked, в Linux вы можете собрать его самостоятельно с помощью сборки , если вы не хотите использовать мьютексы с большим весом и условные переменные.

Если вы не против GPL, тогда http://www.threadingbuildingblocks.org и его шаблон atomic<> кажутся многообещающими. Библиотека кроссплатформенная.

2 голосов
/ 19 июня 2010

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

0 голосов
/ 19 июня 2010

Зависит от вашего компилятора, архитектуры и операционной системы.POSIX (поскольку этот вопрос был помечен как pthreads, я предполагаю, что мы не говорим об windows или какой-либо другой модели потоков) и C не дает достаточных ограничений, чтобы иметь переносимый ответ на этот вопрос.конечно, для защиты доступа к указателю с помощью мьютекса.Однако, основываясь на вашем описании проблемы, я думаю, что pthread_once не будет лучшим способом решения этой проблемы.Конечно, в вопросе недостаточно информации, чтобы сказать так или иначе.

0 голосов
/ 19 июня 2010

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

Используйте мьютекс .. простой enuf .. и вы можете быть уверены, что у вас нет ошибок синхронизации!

0 голосов
/ 19 июня 2010

К сожалению, вы не можете переносить какие-либо предположения о том, что является атомарным в чистом C.

GCC, тем не менее, предоставляет некоторые встроенные атомарные функции, которые заботятся об использовании правильных инструкций для многих архитектур для вас.,Для получения дополнительной информации см. Глава 5.47 руководства GCC .

0 голосов
/ 19 июня 2010

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

...