std::shared_mutex和std::mutex的性能對比(benchmark)

原文作者:@玄冬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的性能對比 */
/************************************************************************/
 
#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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章