У меня есть многопоточные приложения C ++, работающие на ядрах Intel Xeon 32, скомпилированные с GCC 4.8.2 с включенной оптимизацией.
У меня есть несколько потоков (скажем, A, B, C), которые обновляют некоторые PODтипы и другой поток D, который каждые K секунд читает эти переменные и отправляет их в графический интерфейс.Потоки создаются через несколько ядер и сокетов.Записи защищены спин-блокировкой.Поток A, B, C чувствителен к задержке, где высокая производительность является критическим аспектом.Поток D. не чувствителен к задержке.
Что-то вроде:
Thread A,B,C
...
// a,b,c are up to 64 bits (let's say double)
spin-lock
a = computeValue();
b = computeValue();
c = computeValue();
spin-unlock
....
Thread D
...
// a,b,c are up to 64 bits (let's say double)
currValueA = a;
currValueB = b;
currValueC = c;
sendToGui(currValueA ,currValueB ,currValueC );
....
Я хочу воспользоваться пунктом 8.1.1 https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.html, о гарантированных атомарных операциях и избегатьблокировка, защищающая чтения, сделанные потоком D.
Насколько я понимаю, если a, b, c выровнены естественным образом (с размером не больше 64 бит), то нет риска, что поток D сможет прочитать значениедля a, b, c, который берется на полпути во время записи.Другими словами, запись и чтение будут выполняться атомарно.Поток D будет читать либо старое, либо новое значение.
Правильно ли мое понимание?
Я оставил компилятору GCC 4.8.2 позаботиться о выравнивании, т.е.t использовать любые встроенные директивы или функции gcc, такие как std :: alignas, sts :: alignof и т. д.
Я знаю, что код не переносим.Я бы предпочел не использовать std :: atomic, чтобы избежать ненужных накладных расходов.