I wanted to see the performance comparison of std::lock_guard
versus the std::unique_lock
. Even though they both provide slightly different implementations and abilities, the performance impact is worth investigating. So, I wrote the following and tested it on my MacBook Air:
#include <iostream> #include <mutex> #include <cassert> #include <chrono> std::mutex aMutex; // setup a mutex for use void usingLockGuard() { // std::lock_guard locks the mutex and // unlocks at the end of the function // the lock on the mutex is guaranteed std::lock_guard aLock(aMutex); int sum = 0; for(int i = 0; i < 100; ++i) { sum += i; } } void usingUniqueLock() { // std::unique_lock locks the mutex and // unlocks at the end of the function std::unique_lock aLock(aMutex); // the lock on the mutex is not always guaranteed assert(aLock.owns_lock()); int sum = 0; for(int i = 0; i < 100; ++i) { sum += i; } } int main(int argc, const char * argv[]) { // lock guard std::chrono::high_resolution_clock::time_point startTime1 = std::chrono::high_resolution_clock::now(); for(int i = 0; i < 100000; ++i) { usingLockGuard(); } std::chrono::high_resolution_clock::time_point endTime1 = std::chrono::high_resolution_clock::now(); auto elapsedTime1 = std::chrono::duration_cast(endTime1 - startTime1).count(); std::cout << "std::lock_guard elapsed time: " << elapsedTime1 << " microseconds" << std::endl; // unique lock std::chrono::high_resolution_clock::time_point startTime2 = std::chrono::high_resolution_clock::now(); for(int j = 0; j < 100000; ++j) { usingUniqueLock(); } std::chrono::high_resolution_clock::time_point endTime2 = std::chrono::high_resolution_clock::now(); auto elapsedTime2 = std::chrono::duration_cast(endTime2 - startTime2).count(); std::cout << "std::unique_lock elapsed time: " << elapsedTime2 << " microseconds " << std::endl; return 0; }
Here are the typical results:
std::lock_guard elapsed time: 29400 microseconds std::unique_lock elapsed time: 29459 microseconds
So, on average the performance of unique_lock
is comparable in my experience to lock_guard
. Although, there is some additional overhead expected with unique_lock
, but I haven’t noticed it in the above experiment. YMMV.