Почему memory_order_relaxed и memory_order_seq_cst не имеют значения?
Я играл с одним из примеров в C ++ Concurrency in Action, который используетstd::memory_order_relaxed
для чтения и записи 3 атомных переменных из 5 разных потоков. Пример программы выглядит следующим образом:
#include <thread>
#include <atomic>
#include <iostream>
std::atomic<int> x(0);
std::atomic<int> y(0);
std::atomic<int> z(0);
std::atomic<bool> go(false);
const unsigned int loop_count = 10;
struct read_values
{
int x;
int y;
int z;
};
read_values values1[loop_count];
read_values values2[loop_count];
read_values values3[loop_count];
read_values values4[loop_count];
read_values values5[loop_count];
void increment( std::atomic<int>* v, read_values* values )
{
while (!go)
std::this_thread::yield();
for (unsigned i=0;i<loop_count;++i)
{
values[i].x=x.load( std::memory_order_relaxed );
values[i].y=y.load( std::memory_order_relaxed );
values[i].z=z.load( std::memory_order_relaxed );
v->store( i+1, std::memory_order_relaxed );
std::this_thread::yield();
}
}
void read_vals( read_values* values )
{
while (!go)
std::this_thread::yield();
for (unsigned i=0;i<loop_count;++i)
{
values[i].x=x.load( std::memory_order_relaxed );
values[i].y=y.load( std::memory_order_relaxed );
values[i].z=z.load( std::memory_order_relaxed );
std::this_thread::yield();
}
}
void print( read_values* values )
{
for (unsigned i=0;i<loop_count;++i)
{
if (i)
std::cout << ",";
std::cout << "(" << values[i].x <<","
<< values[i].y <<","
<< values[i].z <<")";
}
std::cout << std::endl;
}
int main()
{
std::thread t1( increment, &x, values1);
std::thread t2( increment, &y, values2);
std::thread t3( increment, &z, values3);
std::thread t4( read_vals, values4);
std::thread t5( read_vals, values5);
go = true;
t5.join();
t4.join();
t3.join();
t2.join();
t1.join();
print( values1 );
print( values2 );
print( values3 );
print( values4 );
print( values5 );
return 0;
}
Каждый раз, когда я запускаю программу, я получаю один и тот же вывод:
(0,10,10),(1,10,10),(2,10,10),(3,10,10),(4,10,10),(5,10,10),(6,10,10),(7,10,10),(8,10,10),(9,10,10)
(0,0,1),(0,1,2),(0,2,3),(0,3,4),(0,4,5),(0,5,6),(0,6,7),(0,7,8),(0,8,9),(0,9,10)
(0,0,0),(0,1,1),(0,2,2),(0,3,3),(0,4,4),(0,5,5),(0,6,6),(0,7,7),(0,8,8),(0,9,9)
(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0)
(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0)
Если я изменю сstd::memory_order_relaxed
вstd::memory_order_seq_cst
программа выдает точно такой же вывод!
Я бы ожидал другой результат от 2-х версий программы. Почему нет разницы между выходом дляstd::memory_order_relaxed
а такжеstd::memory_order_seq_cst
?
Почемуstd::memory_order_relaxed
всегда выдают одинаковые результаты при каждом запуске программы?
Я использую: - 32-битную Ubuntu, установленную как виртуальную машину (под VMWare) - четырехъядерный процессор INtel - GCC 4.6.1-9
Код компилируется с помощью: g ++ --std = c ++ 0x -g mem-order-relaxed.cpp -o relaxed -pthread
Обратите внимание, что -pthread необходим, в противном случае сообщается о следующей ошибке: прекращение вызова после выброса экземпляра 'std :: system_error' what (): операция не разрешена
Поведение, которое я вижу из-за отсутствия поддержки с GCC, или в результате работы под VMWare?