ЦП присваивает значение атомарно памяти?

Быстрый вопрос я задавался вопросом о в течение некоторого времени; Делает ЦП, присваивают значения атомарно, или, это поразрядно (скажите, например, что целое число на 32 бита).
Если это является поразрядным, другой мог бы распараллелить доступ к этому точному местоположению, получают "часть" присвоенного будущим образом значения?

Думайте об этом:
У меня есть два потока, и одна общая "неподписанная международная" переменная (назовите это "g_uiVal").
Оба цикла потоков.
На печатает "g_uiVal" с printf (" %u\n", g_uiVal).
Вторые просто увеличивают это число.
Печать распараллелит, когда-нибудь печатают что-то, что является полностью не или часть значения "g_uiVal"?

В коде:

unsigned int g_uiVal;

void thread_writer()
{
 g_uiVal++;
}
void thread_reader()
{
 while(1)
  printf("%u\n", g_uiVal);
}
9
задан Poni 23 May 2010 в 18:23
поделиться

7 ответов

Зависит от ширины шины ЦП и памяти. В контексте ПК, с чем-либо, кроме действительно древнего ЦП, доступ до 32-битного доступа является атомарным; 64-битные обращения могут быть, а могут и не быть. Во встроенном пространстве многие (большинство?) Процессоров имеют ширину 32 бита, и нет возможности для чего-то более широкого, поэтому ваш int64_t гарантированно будет неатомарным.

5
ответ дан 4 December 2019 в 21:48
поделиться

Я считаю, что единственный правильный ответ - «это зависит от обстоятельств». О чем вы спросите?

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

Многие компиляторы предлагают «встроенные функции» для выполнения правильных атомарных операций. Это расширения, которые действуют как функции, но генерируют правильный код для вашей целевой архитектуры, чтобы получить необходимые атомарные операции. Например: http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html

3
ответ дан 4 December 2019 в 21:48
поделиться

В своем вопросе вы сказали «бит за битом». Я не думаю, что какая-либо архитектура выполняет операции понемногу, за исключением некоторых специализированных шин последовательного протокола. Стандартные операции чтения / записи в память выполняются с 8, 16, 32 или 64 битами гранулярности. Итак, ВОЗМОЖНО, что операция в вашем примере является атомарной.

Однако ответ сильно зависит от платформы.

  • Это зависит от возможностей процессора. Может ли оборудование выполнять атомарную 32-битную операция? Вот подсказка: если переменная, над которой вы работаете, больше чем размер собственного регистра (например, 64-битное int в 32-битной системе), это определенно НЕ атомный.
  • Это зависит от того, как компилятор генерирует машинный код. Это могло бы превратили вашу 32-битную переменную доступ к 4x 8-битным операциям чтения памяти.
  • Сложно, если адрес вы получаете доступ не выровнен через естественное слово машины граница. Вы можете попасть в кеш ошибка или ошибка страницы.

ОЧЕНЬ ВОЗМОЖНО, что вы увидите поврежденное или неожиданное значение, используя опубликованный вами пример кода.

Ваша платформа, вероятно, предоставляет некоторый метод выполнения атомарных операций. В случае платформы Windows это осуществляется через взаимосвязанные функции . В случае Linux / Unix посмотрите на тип atomic_t .

1
ответ дан 4 December 2019 в 21:48
поделиться

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

0
ответ дан 4 December 2019 в 21:48
поделиться

Чтобы добавить к тому, что было сказано до сих пор - еще одной потенциальной проблемой является кэширование. Процессоры обычно работают с локальным (на матрице) кэшем памяти, который может быть или не быть немедленно сброшен обратно в основную память. Если в системе более одного процессора, возможно, что другой процессор не увидит изменений в течение некоторого времени после того, как их сделал изменяющий процессор - если только не существует команды синхронизации, сообщающей всем процессорам, что они должны синхронизировать свои внутренние кэши. Как вы можете себе представить, такая синхронизация может значительно замедлить обработку.

0
ответ дан 4 December 2019 в 21:48
поделиться

Учитывая современные микропроцессоры (и игнорируя микроконтроллеры), 32-битное присвоение является атомарным, а не побитовым.

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

0
ответ дан 4 December 2019 в 21:48
поделиться

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

0
ответ дан 4 December 2019 в 21:48
поделиться
Другие вопросы по тегам:

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