原文作者:@玄冬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。
相关推荐
下面是std::shared_ptr的总结和使用示例代码详解: 一、智能指针的用途 std::shared_ptr的主要用途是方便资源的管理,自动释放没有指针引用的资源。它使用引用计数来标识是否有多余指针指向该资源。 二、引用计数...
在多线程编程中,std::shared_mutex提供了一种平衡性能和并发性的方法。读写锁允许多个线程同时进行读操作,这可以显著提高并发性能。然而,对于性能敏感的应用来说,即使是标准库实现也可能有优化空间。这个案例...
它提供了一个高效的方式来实现线程同步,提高了程序的性能和可靠性。 相关知识点: * std::condition_variable 的使用 * std::mutex 的使用 * std::unique_lock<std::mutex> 的使用 * std::condition_variable_any...
在C++11中,`std::mutex`是并发编程中的基础组件,它提供...在实际的并发编程中,`std::mutex`及其相关工具是保证数据一致性、避免竞态条件和死锁的关键。理解并正确使用它们对于编写高效且线程安全的C++代码至关重要。
`std::shared_mutex`提供了一种方式来控制共享和非共享(独占)访问,类似于读写锁。我们可以使用`lock_shared()`方法获取读锁,`lock()`方法获取写锁,而`unlock()`用于释放锁。 ```cpp #include <mutex> class ...
标题和描述中提到的“将任何对象的线程安全性和std::shared_mutex的速度提高10倍”,这意味着该库通过优化对 std::shared_mutex 的使用,实现了在高读取率(超过85%)时,接近无锁算法的性能。 `std::shared_mutex`...
当多个线程同时读取共享数据但写入操作是互斥的,`std::shared_mutex`(或旧版的`std::boost::shared_mutex`)可以提高效率。多个线程可以同时持有读锁,但写锁是互斥的。 ```cpp #include <mutex> std::shared_...
这个简单的读写锁实例展示了如何在C++中使用`std::shared_mutex`和`std::mutex`来实现并发控制。然而,实际应用中可能需要考虑更多因素,比如异常安全、死锁预防等。在设计和使用读写锁时,应充分理解其工作原理,并...
C++11中的各种mutex, lock对象,实际上都是对posix的mutex,condition的封装。不过里面也有很多细节值得学习。 std::mutex 先来看下std::mutex: 包增了一个pthread_mutex_t __m_,很简单,每个函数该干嘛...
通过编写测试用例,我们可以验证它们的正确性和性能。测试应包括正常运行、重置、停止以及在多线程环境下的行为等场景。 总结来说,C++的`<chrono>`库为我们提供了构建毫秒级定时器的基础。这两个示例类展示了如何...
`1_pthread_mutex.tgz`、`1_pthread_mutex`、`1_pthread_deadlock`和`1_pthread_basic`这些文件名可能包含了一些示例代码,比如展示了如何初始化、锁定、解锁互斥锁,以及如何处理可能出现的死锁问题。死锁是指两个...
在`TestThreadPool.sln`解决方案中,开发者可能会创建一个测试程序,用于实例化线程池并提交一些任务,以验证线程池的正确性和性能。这通常涉及到创建一个主函数,创建线程池实例,然后使用`enqueue()`提交一系列...
为了保证线程安全,我们使用`std::mutex`和`std::condition_variable`进行同步。 工作线程的实现如下: ```cpp void ThreadPool::worker() { while (!stop) { std::function()> task; { std::unique_lock<std...
C++提供了多种同步原语,如`std::mutex`(互斥锁)、`std::condition_variable`(条件变量)、`std::future`和`std::promise`(异步计算)。例如,使用`std::mutex`保护共享资源: ```cpp std::mutex m; void ...
#0 0x00002b9405ea1c38 in __lll_mutex_lock_wait () from /lib64/libc.so.6 #1 0x00002b9405e45e5f in _L_lock_4026 () from /lib64/libc.so.6 #2 0x00002b9405e42df1 in free () from /lib64/libc.so.6 #3 0x00002...
它比boost::shared_mutex快。 lock_shared非常贪婪,因此等待lock时间是不公平的。 这应该没有问题,因为此互斥对象适用于被动写入器-主动读取器方案。 最好情况下, lock_shared只是一个fetch_add 。 在最佳...
`mutex`(互斥锁)和`semaphore`(信号量)都是用于实现线程同步和互斥的工具,确保同一时间只有一个线程可以访问特定的共享资源。本文将深入探讨这两种机制及其在实际编程中的应用。 一、互斥锁(Mutex) 互斥锁是...
`std::lock_guard`是一个智能指针,用于自动管理`mutex`的锁定和解锁。例如: ```cpp #include <mutex> #include std::vector<int> shared_data; std::mutex data_mutex; void modify_data(int value) { std::...
在 C++11 中,我们可以使用 std::mutex、std::condition_variable 和 std::queue 等标准库来实现阻塞队列。 阻塞队列的实现需要注意以下几点: 1. 线程安全:使用 std::mutex 来保护队列的读写操作,避免多线程...