單線程中加鎖代碼的性能如何?

假設我有一個函數:

bool insert(int id, std::shared_ptr& p)
{
std::lock_guard& lock(m_lock);
auto it = m_client.insert(make_pair(id, p));
return it.second;
}

為了保護m_client容器,進行了枷鎖。

但是有一天,我突然發現,我需要把它弄成單線程的。但是整個程序我並不想去逐條修改將鎖去掉,所以,在單線程環境中,加鎖這一句能耗費多少性能?是否值得我去修改?

或者換一個說法,如何能通過指定一個編譯參數,讓這個鎖再單線程環境下失效。

之前的老做法,是自己寫的lock_guard,再單線程下,會把lock_guard定義為:

#define lock_guard(x) x

這樣,再O3優化,就會把x優化掉。

如果我現在使用的,是C++11的std::lock_guard呢?有什麼辦法?


總體來說,沒有很多Conflict的時候,鎖的速度是很快的。

在VS2013 Update 4上,這段代碼最終會變成執行一個CAS的原子操作,在我的i7-3770k上,每1M次大約需要4ms。

因此如果調用次數有限,或者Profiling的時候沒說它是瓶頸,那就可以不管。


你可以參考boost.pool的做法,定義no lock mutex,並把mutex作為template參數。no lock mutex基本實現就是空的,lock guard也會因此被優化掉。

但是,這麼搞一下改動量也不小。


這裡有四處性能損耗在一個量級的代碼 mutex sharedptr 紅黑樹節點new 紅黑樹插入調整

只修改一處目測帶來的性能提升小於25%

從經驗上看這段代碼不屬於項目的核心處理代碼 修改無意義

另外多說一句 換個宏定義方法 可以不開啟優化選項把那行代碼優化掉的


參考一篇文章 roll your own lightweight mutex

一般鎖實現 是輕量級鎖,先執行一條輕量級cas 若失敗則執行 重量級系統調用。

單線程下,完全沒有競爭, 因此所有鎖只執行了 cas 原子指令。

文章里 100萬次輕量級鎖,大概幾十ns


必然高效啊 Java都有偏向鎖和棧鎖了 那cpp必然更有啊


就linux來說,mutex現在的實現在沒有鎖競爭的時候已經足夠快了,不需要陷入內核執行futex系統調用,只需要幾條指令,一條CAS操作,所以一般不會成為性能瓶頸。mutex的耗時都是耗在有競爭時的上下文切換以及進程被睡眠。


推薦閱讀:

redis為什麼是單線程?在多核處理器下對主存的訪問真的比多線程更有效率?未來有可能改用多線程嗎?
malloc和free是線程安全的嗎,在多線程開發時用這兩個函數應該注意什麼?
Python有GIL為什麼還需要線程同步?
像網路爬蟲、資料庫等方面多線程程序如何設置線程數?
UDP socket能否被多線程同時調用sendto來發送數據?

TAG:編程 | C | Linux開發 | 多線程 | 單線程 |