原文作者:@玄冬Wong
转载请注明原文出处:http://aigo.iteye.com/blog/2296462
key world: std::shared_mutex、std::mutex、performance、benchmark、性能测试
shared_mutex的适用场景比较特殊:一个或多个读线程同时读取共享资源,且只有一个写线程来修改这个资源,这种情况下才能从shared_mutex获取性能优势。
cppreference文档
http://en.cppreference.com/w/cpp/thread/shared_mutex
Shared mutexes are usually used in situations when multiple readers can access the same resource at the same time without causing data races, but only one writer can do so.
测试代码:
注意,VC第一个支持shared_mutex的版本是VS2015 update2
/************************************************************************/
/* std::shared_mutex与std::mutex的性能对比 */
/************************************************************************/
#pragma once
#define WRITE_THREAD_COUNT 8
#define LOOP_COUNT 5000000
#include <iostream>
#include <mutex> // For std::unique_lock
#include <shared_mutex>
#include <thread>
class shared_mutex_counter {
public:
shared_mutex_counter() = default;
// Multiple threads/readers can read the counter's value at the same time.
unsigned int get() const {
std::shared_lock<std::shared_mutex> lock(mutex_);
return value_;
}
// Only one thread/writer can increment/write the counter's value.
void increment() {
std::unique_lock<std::shared_mutex> lock(mutex_);
value_++;
}
// Only one thread/writer can reset/write the counter's value.
void reset() {
std::unique_lock<std::shared_mutex> lock(mutex_);
value_ = 0;
}
private:
mutable std::shared_mutex mutex_;
unsigned int value_ = 0;
};
class mutex_counter {
public:
mutex_counter() = default;
unsigned int get() const {
std::unique_lock<std::mutex> lk(mutex_);
return value_;
}
void increment() {
std::unique_lock<std::mutex> lk(mutex_);
value_++;
}
private:
mutable std::mutex mutex_;
unsigned int value_ = 0;
};
void test_shared_mutex()
{
shared_mutex_counter counter;
int temp;
auto writer = [&counter]() {
for (int i = 0; i < LOOP_COUNT; i++) {
counter.increment();
}
};
auto reader = [&counter, &temp]() {
for (int i = 0; i < LOOP_COUNT; i++) {
temp = counter.get();
}
};
std::thread** tarray = new std::thread*[WRITE_THREAD_COUNT];
clock_t start = clock();
for (int i = 0; i < WRITE_THREAD_COUNT; i++)
{
tarray[i] = new std::thread(reader);
}
std::thread tw(writer);
for (int i = 0; i < WRITE_THREAD_COUNT; i++)
{
tarray[i]->join();
}
tw.join();
clock_t end = clock();
printf("[test_shared_mutex]\n");
printf("thread count:%d\n", WRITE_THREAD_COUNT);
printf("result:%d cost:%dms temp:%d \n", counter.get(), end - start, temp);
}
void test_mutex()
{
mutex_counter counter;
int temp;
auto writer = [&counter]() {
for (int i = 0; i < LOOP_COUNT; i++) {
counter.increment();
}
};
auto reader = [&counter, &temp]() {
for (int i = 0; i < LOOP_COUNT; i++) {
temp = counter.get();
}
};
std::thread** tarray = new std::thread*[WRITE_THREAD_COUNT];
clock_t start = clock();
for (int i = 0; i < WRITE_THREAD_COUNT; i++)
{
tarray[i] = new std::thread(reader);
}
std::thread tw(writer);
for (int i = 0; i < WRITE_THREAD_COUNT; i++)
{
tarray[i]->join();
}
tw.join();
clock_t end = clock();
printf("[test_mutex]\n");
printf("thread count:%d\n", WRITE_THREAD_COUNT);
printf("result:%d cost:%dms temp:%d \n", counter.get(), end - start, temp);
}
int main() {
//为了排除测试程序的无关因素,测试时只开启一个
//test_shared_mutex();
test_mutex();
}
测试结果:
2线程抢占
[test_mutex]
thread count:2
result:10000000 cost:1348ms temp:10000000
[test_shared_mutex]
thread count:2
result:10000000 cost:699ms temp:10000000
4线程抢占
[test_mutex]
thread count:4
result:10000000 cost:2448ms temp:10000000
[test_shared_mutex]
thread count:4
result:10000000 cost:1233ms temp:10000000
8线程抢占
[test_mutex]
thread count:8
result:5000000 cost:2452ms temp:5000000
[test_shared_mutex]
thread count:8
result:5000000 cost:1123ms temp:3231860
结论:
在多个只读线程和一个写线程的情况下,shared_mutex比mutex快一倍。
PS:std::shared_mutex和std::mutex分别对应java中的ReentrantReadWriteLock、ReentrantLock。