2013-12-08 4 views
3

Учитывая структуру, как это:В какой степени должны использоваться атомарные типы, чтобы гарантировать видимость поперечной резьбы?

struct foo { 
    atomic_int refcount; /* atomic access */ 
    char* bar1;   /* read-only */ 
    char* bar2;   /* read-only */ 
}; 

Строго говоря: это необходимо использовать atomic_intptr_t для bar1 и bar2, чтобы гарантировать видимость кросс-нить из неатомарных переменных, разумеющимся, что я использую надлежащего сбора по/выпуска семантика?

ответ

3

Взято абстрактно, любые операции с памятью, которые происходят между операциями получения/освобождения от атомной переменной, будут вести себя так, как если бы вы приобрели и выпустили абстрактный тип мьютекса (POSIX, WinAPI и т. Д.), Поскольку именно так они реализованы так или иначе. Основная задача атомных операций и определенной модели памяти - определить, как упорядочиваются неатомные обращения к памяти при атомарном доступе. Поэтому они не должны быть атомарными.

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

полезное чтение (я не уверен в каких-либо различий между С11 и 11 C++ в модели памяти): http://en.cppreference.com/w/cpp/atomic/memory_order

http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/

EDIT: Добавлена ​​ссылка лучше.

1

Чтобы быть педантичным (что хорошо, когда речь идет о моделях памяти), нет ничего, что человек ­ даты, которые меняются становятся видимыми для других тем. Все, что вам гарантировано, - это то, что происходит в точке синхронизации: Если вы получили, ваше приобретение прочитает определенное, новое значение, , тогда вам гарантировано, что все эффекты потока, которые использовали запись-релиз, чтобы записать это новое значение которые появились до того, как запись в этом потоке произошла и видна. Но у вас на самом деле нет гарантии , что ваш приобретатель ­ ing-read будет когда-либо читать новое значение.

C++ 11 немного более подробно об этом и содержит «Примечание», что «операция станет видимой для всех других потоков за конечный период времени» (C++ 11, 1.10/25), но Я не вижу аналогов в C11.

(я на самом деле написал комментарий к этому вопросу на Herb Sutter's atomic talk.)

+0

Я до сих пор перевариваю этот ответ, но мне интересно, если пара приобретает/релиз действительно наблюдать новое значение ('RefCount '), будут ли неатомные поля видны и для других потоков? В этом случае я инициализирую 'bar1' и' bar2', а затем опубликую структуру, установив 'refcount' в 1 и разместив его где-нибудь. В принципе, я не могу рисковать другими потоками, видя мусор в неатомных полях. – haste

+1

@haste: Они не будут видеть мусор. Тем не менее, я говорю, что они могут * никогда не видеть новое значение. Стандарт только гарантирует, что * если * вы видите новое значение в паре приобретения/выпуска, * затем * все эффекты до релиза видны. Но я не вижу никаких гарантий, что «все в конечном итоге распространяется». –

+0

Существует два исключения. Если вы используете RMW, вы получаете более мощную семантику, так как только одно действие RMW может читать из данной записи. Тогда, конечно, последовательно последовательные гарантии, что вы видите последние значения. – briand

 Смежные вопросы

  • Нет связанных вопросов^_^