提高性能的一種方式 atomic 替換mutex
內存序跟原子操作本身並不衝突, 不論用那種內存序該原子還是原子操作
atomic內存序: 就是來指定順序的
例子:
注 : 像類似 memory_order_relaxed 都是以函數爲單位來重新排執行指令的 [這個註釋後面再來看好了]
#include <atomic>
atomic<int> a (0);
atomic<int> b(0);
unsigned int __stdcall thread_write(void *ar){
int hahah = 123; //1
int balala = hahah; //2
a.store(1,std::memory_order_relaxed); //3
b.store(666,std::memory_order_relaxed); //4
bool ooo = false; //7
return 0;
}
unsigned int __stdcall thread_read(void * arg){
while(b.load(std::memory_order_relaxed) != 666); //5
int r = a.load(std::memory_order_relaxed); //6
cout << "a : " << r << endl;
assert( r ==1 );
return 0;
}
int main(int argc, char* argv[])
{
HANDLE t1 = (HANDLE)_beginthreadex(0,0,thread_read,0,0,0);
HANDLE t2 = (HANDLE)_beginthreadex(0,0,thread_write,0,0,0);
while(1){
Sleep(1000);
}
cout << "main done" << endl;
return 0;
}
memory_order_relaxed 隨意的順序 , 怎麼個意思呢?
thread_write 中 1,2 是固定的, 3,4,7可以隨意,即 1,2, 3,4,7 / 1,2,4,3,7 / 7,4,3,1,2 等
thread_read 中 5,6 隨意
因此,thread_read中的 6 在弱內存模型中【意思是把指令重排,提高並行能力 => 編譯器乾的】 不一定是 1 ,可以是0,或者1;
比如 thread_read 中 a.load 將先執行, thread_write還沒開始,則 a == 0;
那麼如何保證寫的順序呢? memory_order_release
如果你熟悉多線程,那麼可以這麼理解:
lock() -> 做一些事 -> unlock() -> ( ReleaseSemaphore 或者 sem_post)
如果不熟悉多線程, 那麼就從字面意思理解好了, release 相當於生成一個release 版本的程序, 即前面的該有的操作都完成了才
能生成一個release 版本;
代碼: 修改 thread_write
unsigned int __stdcall thread_write(void *ar){
int hahah = 123; //1
a.store(1,std::memory_order_relaxed); //2
//修改這裏
b.store(666,std::memory_order_release); //3
return 0;
}
memory_order_release 的意思是 1,2 隨意,但不能放到我後面, 到我這,你們前面的該執行該完成都得搞完;
到此, thread_read 函數能夠保證正確嗎?
unsigned int __stdcall thread_read(void * arg){
while(b.load(std::memory_order_relaxed) != 666);
int r = a.load(std::memory_order_relaxed);
assert( r ==1 );
return 0;
}
很不幸, 不能!
memory_order_release 在thread_write 函數中保證了執行指令的順序
thread_read 中並沒有任何保證; a.load 還是有可能被先執行;
相當於 :
1. a.load
2. while( b.load() )
接下來就是輪到 memory_order_acquire 這個東西; 修改一行代碼即可;
unsigned int __stdcall thread_read(void * arg){
while(b.load(std::memory_order_acquire) != 666);
int r = a.load(std::memory_order_relaxed);
assert( r ==1 );
return 0;
}
意思是, 此處的指令 編譯器你別給我亂動,就按這個順序來.
如果熟悉mutex, 就把此處當 lock 即可;