Подтвердить что ты не робот

Меняет ли указатель на атомное действие в C?

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

Как я вижу, если изменение является атомарным, другие потоки будут либо читать старшее значение, либо новое значение; никогда не случайная память (или нулевые указатели), правильно?

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

Является ли указатель изменен атомарным?

Обновление. Моя платформа - это 64-разрядная версия Linux (2.6.29), хотя мне также нужен кросс-платформенный ответ:)

4b9b3361

Ответ 1

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

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

Например, нарушается следующий код:

Тема А:

DoWork();
workDone = 1;

Тема B:

while(workDone != 0);

ReceiveResultsOfWork();

Хотя запись в workDone является атомарной, во многих системах процессор не гарантирует, что запись в workDone будет видна другим процессорам, прежде чем записи, сделанные с помощью DoWork(), будут видны. Компилятор также может свободно перенаправлять запись на workDone до вызова DoWork(). В обоих случаях ReceiveResultsOfWork() может начать работать с неполными данными.

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

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

Ответ 2

Язык C ничего не говорит о том, являются ли какие-либо операции атомарными. Я работал над микроконтроллерами с 8-битными шинами и 16-разрядными указателями; любая операция указателя на этих системах потенциально будет неатомной. Я думаю, что я помню Intel 386s (некоторые из которых имели 16-битные шины), вызывающие подобные проблемы. Аналогичным образом, я могу представить системы с 64-битными процессорами, но 32-разрядные шины данных, которые могут повлечь за собой аналогичные проблемы, связанные с неатомными операциями указателя. (Я не проверял, существуют ли такие системы на самом деле.)

РЕДАКТИРОВАТЬ: Майкл ответ стоит прочитать. Размер шины по сравнению с размером указателя вряд ли является единственным соображением относительно атомарности; это был просто первый контрпример, который пришел мне на ум.

Ответ 3

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

Являются ли переменные указателя облачными?

Различие необходимо, потому что различные реализации C/С++ могут отличаться в этом поведении. Возможно, что определенная платформа гарантирует атомарные присвоения и все еще находится в пределах стандарта.

Что касается того, гарантировано ли это в целом на C/С++, ответ №. Стандарт C не дает таких гарантий. Единственный способ гарантировать назначение указателя - это использовать механизм, специфичный для платформы, чтобы гарантировать атомарность назначения. Например, методы блокировки в Win32 предоставят эту гарантию.

На какой платформе вы работаете?

Ответ 4

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

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

Ответ 5

"нормальная" модификация указателя не гарантируется атомарной.

проверить 'Compare and Swap' (CAS) и другие атомные операции, а не стандарт C, но большинство компиляторов имеют некоторый доступ к примитивам процессора. в случае GNU gcc существует несколько встроенных функций

Ответ 6

Единственное, что гарантируется стандартом, это тип sig_atomic_t.

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

Если вы действительно отчаянно хотите знать, вы можете сравнить sizeof (sig_atomic_t) с sizeof (int *) и посмотреть, какова ваша целевая система.

Ответ 7

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

Благоразумная архитектура будет использовать блокировку.