Я немного запутался:
В производстве у нас есть два процесса, взаимодействующих через общую память, часть обмена данными - это long и bool. Доступ к этим данным не синхронизирован. Долгое время все работало нормально и до сих пор работает. Я знаю, что изменение значения не является атомарным, но, учитывая, что эти значения изменяются / к ним обращаются миллионы раз, это должно было произойти?
Вот пример кода, который обменивается числом между двумя потоками:
#include <pthread.h>
#include <xmmintrin.h>
typedef unsigned long long uint64;
const uint64 ITERATIONS = 500LL * 1000LL * 1000LL;
//volatile uint64 s1 = 0;
//volatile uint64 s2 = 0;
uint64 s1 = 0;
uint64 s2 = 0;
void* run(void*)
{
register uint64 value = s2;
while (true)
{
while (value == s1)
{
_mm_pause();// busy spin
}
//value = __sync_add_and_fetch(&s2, 1);
value = ++s2;
}
}
int main (int argc, char *argv[])
{
pthread_t threads[1];
pthread_create(&threads[0], NULL, run, NULL);
register uint64 value = s1;
while (s1 < ITERATIONS)
{
while (s2 != value)
{
_mm_pause();// busy spin
}
//value = __sync_add_and_fetch(&s1, 1);
value = ++s1;
}
}
Как видите, я прокомментировал несколько вещей:
// volatile uint64 s1 = 0;
и
// value = __sync_add_and_fetch (& s1, 1);
__ sync_add_and_fetch атомарно увеличивает переменную.
Я знаю, что это не очень научно, но несколько раз без синхронизирующих функций работает совершенно нормально. Кроме того, если я измерил синхронизацию обеих версий и без синхронизации они работают с одинаковой скоростью, почему __sync_add_and_fetch не добавляет никаких издержек?
Я предполагаю, что компилятор гарантирует атомарность для этих операций, и поэтому я не вижу проблемы в производстве. Но все еще не могу объяснить, почему __sync_add_and_fetch не добавляет никаких накладных расходов (даже работает в режиме отладки).
Еще несколько подробностей о шахтной среде:
Ubuntu 10.04, gcc4.4.3
Intel i5 многоядерный процессор.
Производственная среда похожа, она работает только на более мощных процессорах и на ОС Centos.
спасибо за вашу помощь