我在玩C++ Concurrency in Action中的一個例子,它使用std::memory_order_relaxed
來從5個不同的線程讀取和寫入3個原子變量。示例程序如下:爲什麼memory_order_relaxed和memory_order_seq_cst沒有區別?
#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
程序給出完全相同的輸出!
我本來會期望來自該程序的兩個版本的不同輸出。爲什麼std::memory_order_relaxed
和std::memory_order_seq_cst
的輸出之間沒有什麼區別?
爲什麼std::memory_order_relaxed
對於程序的每次運行都會產生完全相同的結果?
我使用: - 32位的Ubuntu安裝爲一個虛擬機(下VMWare的) - - 英特爾四核處理器 GCC 4.6.1-9
的代碼被編譯: 克++ - std = C++ 0x -g mem-order-relaxed.cpp -o relaxed -pthread
注意-pthread是必需的,否則會報告以下錯誤: 在拋出std :: system_error' what():不允許操作
由於缺乏對GCC的支持,或者由於在VMWare下運行,我看到的行爲是什麼?
您已將多少個處理器內核分配給VM? – 2012-03-27 09:10:14
@Michael Burr - 這就解決了--Vmware被設置爲1核心,現在我已經將它設置爲4核心,我得到了預期的結果。不得不承認我是使用VMWare的新手 - 我習慣於將Linux作爲本機操作系統。如果你發佈你的建議,我會接受它作爲答案。乾杯。 – mark 2012-03-27 09:41:05