当前位置:网站首页>手撕读写锁性能测试
手撕读写锁性能测试
2022-07-30 12:13:00 【君梦如烟Brian】
测试代码
基本思路:
先用CountDownLatch
(详见下节,并发用具) 同步子线程创建,然后,摁下计时器一次,开始测试。
再用另一个CountDownLatch
同步子线程完成任务的情况,最后再按一下计时器。
配置:
1个写线程,7个读线程。同时,内部控制读写次数,为了方便体现读写锁的性能与互斥锁的性能对比,直接调整内部循环的限制次数即可。
粗略的结果:
在写的次数比读的次数要少得多时,读写锁性能比互斥锁要高。
在写得次数比读得次数差不多时,互斥锁性能比读写锁略高。
但是在开启代码优化后,只有写者数量少于读者数量的两个数量级左右,读写锁的性能才开始体现出来。
CountDownLatch startLatch(1);
CountDownLatch endLatch(8);
ReadWriteLock mtx;
int g_count = 0;
void write_something() {
startLatch.wait();
int count = 1000; // thread_local
do {
WriterLockGuard lock(::mtx);
g_count++;
} while (--count);
endLatch.down();
}
void read_something() {
startLatch.wait();
int count = 100000; // thread_local
do {
#ifndef TEST_RWLOCK
WriterLockGuard lock(::mtx);
#else
ReaderLockGuard lock(::mtx);
#endif
} while (--count);
endLatch.down();
}
int main()
{
using namespace std::chrono;
std::vector<std::thread> threads;
for (int i = 0; i != 7; ++i) {
threads.push_back(thread(read_something));
}
for (int i = 0; i != 1; ++i) {
threads.push_back(thread(write_something));
}
startLatch.down();
auto start = std::chrono::system_clock::now();
endLatch.wait();
auto end = std::chrono::system_clock::now();
cout << (g_count == 1000) << endl;
cout << duration_cast<milliseconds>(end - start).count() << " ms" << endl;
for (auto &th : threads) {
th.join();
}
return 0;
}
读写锁实现代码
互斥锁 + 条件变量实现读写锁
class ReadWriteLock {
std::atomic<int> nwait_;
std::condition_variable isNotWriter_;
std::mutex mtx_;
public:
void reader_lock() {
unique_lock<std::mutex> localGuard(mtx_);
while (nwait_ < 0) {
isNotWriter_.wait(localGuard);
}
nwait_++;
}
void reader_unlock() {
lock_guard<std::mutex> localGuard(mtx_);
if (--nwait_ == 0) isNotWriter_.notify_one();
}
void writer_lock() {
unique_lock<std::mutex> localGuard(mtx_);
while (nwait_ != 0) {
isNotWriter_.wait(localGuard);
}
--nwait_;
assert(nwait_ == -1);
}
void writer_unlock() {
lock_guard<std::mutex> localGuard(mtx_);
++nwait_;
assert(nwait_ == 0);
isNotWriter_.notify_all();
}
};
双互斥锁实现读写锁
class ReadWriteLock {
int nwait_;
std::mutex rmtx_;
std::mutex wmtx_;
public:
ReadWriteLock() :nwait_(0) {
}
void reader_lock() {
lock_guard<std::mutex> localGuard(rmtx_);
++nwait_;
if (nwait_ == 1) wmtx_.lock();
}
void reader_unlock() {
lock_guard<std::mutex> localGuard(rmtx_);
--nwait_;
if (nwait_ == 0) wmtx_.unlock();
}
void writer_lock() {
wmtx_.lock();
}
void writer_unlock() {
wmtx_.unlock();
}
};
并发用具
CountDownLatch
java常见的同步工具, 通常用于子线程全部完成任务后汇总给主线程
class CountDownLatch {
size_t count_ = 0;
std::mutex mtx_;
std::condition_variable cond_;
public:
CountDownLatch(size_t count):count_(count) {
assert(count >= 1);
}
void down() {
unique_lock<std::mutex> localGurad(mtx_);
if (--count_ == 0) cond_.notify_all();
}
void wait() {
unique_lock<std::mutex> localGurad(mtx_);
while (count_ != 0) cond_.wait(localGurad);
}
};
LocalGuard
一些巧妙利用RALL机制的线程同步工具
读写锁相关
WriterLockGuard:
class WriterLockGuard {
ReadWriteLock &lock_;
public:
WriterLockGuard(ReadWriteLock& lock) :lock_(lock) {
lock_.writer_lock();
}
~WriterLockGuard() {
lock_.writer_unlock();
}
};
ReaderLockGuard:
class ReaderLockGuard {
ReadWriteLock &lock_;
public:
ReaderLockGuard(ReadWriteLock& lock) :lock_(lock){
lock_.reader_lock();
}
~ReaderLockGuard() {
lock_.reader_unlock();
}
};
更多参考
边栏推荐
猜你喜欢
随机推荐
【ASP.NET Core】选项类的依赖注入
历时两月,终拿字节跳动offer,算法面试题分享「带答案」
从“校园贷”到“直播带货”,追风少年罗敏一直行走在风口浪尖
Niuke-TOP101-BM42
MySQL【多表查询】
概率论的学习和整理--番外4: 关于各种平均数:算术平均数,几何平均数,调和平均数,以及加权平均数和平方平均数 (未完成)
OneNote如何修改已有的笔记本为默认的快速笔记?
概率论的学习整理4:全概率公式
[BJDCTF2020]Cookie is so stable-1|SSTI injection
Rust from entry to proficient 02-installation
CMake library search function does not search LD_LIBRARY_PATH
力扣——15. 三数之和
win下怎么搭建php环境的方法教程
saltstack学习3模块
Reverse linked list - recursive inversion method
PanGu-Coder: 函数级的代码生成模型
维护数千规模MySQL实例,数据库灾备体系构建指南
I built another wheel: GrpcGateway
什么是驱动程序签名,驱动程序如何获取数字签名?
[BJDCTF2020]Cookie is so stable-1|SSTI注入