程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> atomic, spinlock and mutex性能比較,spinlockmutex

atomic, spinlock and mutex性能比較,spinlockmutex

編輯:C++入門知識

atomic, spinlock and mutex性能比較,spinlockmutex


我非常好奇於不同同步原理的性能,於是對atomic, spinlock和mutex做了如下實驗來比較:

1. 無同步的情況

1 #include <future> 2 #include <iostream> 3 4 volatile int value = 0; 5 6 int loop (bool inc, int limit) { 7 std::cout << "Started " << inc << " " << limit << std::endl; 8 for (int i = 0; i < limit; ++i) { 9 if (inc) { 10 ++value; 11 } else { 12 --value; 13 } 14 } 15 return 0; 16 } 17 18 int main () { 19 auto f = std::async (std::launch::async, std::bind(loop, true, 20000000));//開啟一個線程來執行loop函數,c++11的高級特性 20 loop (false, 10000000); 21 f.wait (); 22 std::cout << value << std::endl; 23 } View Code

通過clang編譯器:

1 clang++ -std=c++11 -stdlib=libc++ -O3 -o test test.cpp && time ./test

運行:

1 SSttaarrtteedd  10  2100000000000000
2 
3 11177087
4 
5 real    0m0.070s
6 user    0m0.089s
7 sys 0m0.002s

從運行結果很顯然的我們可以看出增減不是原子性操作的,變量value最後所包含的值是不確定的(垃圾)。

2. 匯編LOCK

1 #include <future> 2 #include <iostream> 3 4 volatile int value = 0; 5 6 int loop (bool inc, int limit) { 7 std::cout << "Started " << inc << " " << limit << std::endl; 8 for (int i = 0; i < limit; ++i) { 9 if (inc) { 10 asm("LOCK"); 11 ++value; 12 } else { 13 asm("LOCK"); 14 --value; 15 } 16 } 17 return 0; 18 } 19 20 int main () { 21 auto f = std::async (std::launch::async, std::bind(loop, true, 20000000)); //開啟一個線程來執行loop函數,c++11的高級特性 22 loop (false, 10000000); 23 f.wait (); 24 std::cout << value << std::endl; 25 } View Code
1 SSttaarrtteedd  10  2000000100000000
2 
3 10000000
4 
5 real    0m0.481s
6 user    0m0.779s
7 sys 0m0.005s

  在最後變量value得到了正確的值,但是這些代碼是不可移植的(平台不兼容的),只能在X86體系結構的硬件上運行,而且要想程序能正確運行編譯的時候必須使用-O3編譯選項。另外,由於編譯器會在LOCK指令和增加或者減少指令之間注入其他指令,因此程序很容易出現“illegal instruction”異常從而導致程序被崩潰。

3. 原子操作atomic

1 #include <future> 2 #include <iostream> 3 #include "boost/interprocess/detail/atomic.hpp" 4 5 using namespace boost::interprocess::ipcdetail; 6 7 volatile boost::uint32_t value = 0; 8 9 int loop (bool inc, int limit) { 10 std::cout << "Started " << inc << " " << limit << std::endl; 11 for (int i = 0; i < limit; ++i) { 12 if (inc) { 13 atomic_inc32 (&value); 14 } else { 15 atomic_dec32 (&value); 16 } 17 } 18 return 0; 19 } 20 21 int main () { 22 auto f = std::async (std::launch::async, std::bind (loop, true, 20000000)); 23 loop (false, 10000000); 24 f.wait (); 25 std::cout << atomic_read32 (&value) << std::endl; 26 } View Code

運行:

1 SSttaarrtteedd  10  2100000000000000
2 
3 10000000
4 
5 real    0m0.457s
6 user    0m0.734s
7 sys 0m0.004s

最後結果是正確的,從所用時間來看跟匯編LOCK的差不多。當然原子操作的底層也是使用了LOCK匯編來實現的,只不過是使用了可移植的方法而已。

4. 自旋鎖spinlock

1 #include <future> 2 #include <iostream> 3 #include "boost/smart_ptr/detail/spinlock.hpp" 4 5 boost::detail::spinlock lock; 6 volatile int value = 0; 7 8 int loop (bool inc, int limit) { 9 std::cout << "Started " << inc << " " << limit << std::endl; 10 for (int i = 0; i < limit; ++i) { 11 std::lock_guard<boost::detail::spinlock> guard(lock); 12 if (inc) { 13 ++value; 14 } else { 15 --value; 16 } 17 } 18 return 0; 19 } 20 21 int main () { 22 auto f = std::async (std::launch::async, std::bind (loop, true, 20000000)); 23 loop (false, 10000000); 24 f.wait (); 25 std::cout << value << std::endl; 26 } View Code

運行:

1 SSttaarrtteedd  10  2100000000000000
2 
3 10000000
4 
5 real    0m0.541s
6 user    0m0.675s
7 sys 0m0.089s

最後結果是正確的,從用時來看比上述的慢點,但是並沒有慢太多

5. 互斥鎖mutex

1 #include <future> 2 #include <iostream> 3 4 std::mutex mutex; 5 volatile int value = 0; 6 7 int loop (bool inc, int limit) { 8 std::cout << "Started " << inc << " " << limit << std::endl; 9 for (int i = 0; i < limit; ++i) { 10 std::lock_guard<std::mutex> guard (mutex); 11 if (inc) { 12 ++value; 13 } else { 14 --value; 15 } 16 } 17 return 0; 18 } 19 20 int main () { 21 auto f = std::async (std::launch::async, std::bind(loop, true, 20000000)); 22 loop (false, 10000000); 23 f.wait (); 24 std::cout << value << std::endl; 25 } View Code

運行:

1 SSttaarrtteedd  10  2010000000000000
2 
3 10000000
4 
5 real    0m25.229s
6 user    0m7.011s
7 sys 0m22.667s

互斥鎖要比前面幾種的慢很多

1 Benchmark
2 Method    Time (sec.)
3 No synchronization     0.070
4 LOCK     0.481
5 Atomic     0.457
6 Spinlock     0.541
7 Mutex     22.667

當然,測試結果會依賴於不同的平台和編譯器(我是在Mac Air和clang上做的測試)。

 

原文鏈接:http://demin.ws/blog/english/2012/05/05/atomic-spinlock-mutex/

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved