当前位置:网站首页>手撕读写锁性能测试
手撕读写锁性能测试
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();
}
};
更多参考
边栏推荐
猜你喜欢
随机推荐
备战金九银十!2022面试必刷大厂架构面试真题汇总+阿里七面面经+架构师简历模板分享
别被隐私计算表象骗了 | 量子位智库报告(附下载)
基于DoS攻击能量分级的ICPS综合安全控制与通信协同设计
JS事件的相关特性以及原理
开源出来的fuse版pfs文件系统主要就是解决缓存问题吧。nfs挂载参数带sync规避缓存问题是不是
概率论得学习和整理6:概率的分布
[SCTF2019]Flag Shop
CV-Model【2】:MobileNet v1
基于反步积分滑模摩擦补偿的光电伺服转台控制
概率论的学习整理1: 集合和事件
北上广线下活动丨年底最不可错过的技术聚会都齐了
Underwater target detection method based on spatial feature selection
企业如何成功完成云迁移?
初级永磁直线电机双动子电流镜像容错控制
SCM engineers written questions induction summary
【记一个kaggle划水比赛】PetFinder.my - Pawpularity Contest 宠物预测
Flexible distribution parameters of mechanical system modeling and control of research and development
ModelCoder状态机:对柴油机工况判断策略进行建模
Matlab绘图(1)——二维绘图
Kubernetes之本地存储







![[SCTF2019]Flag Shop](/img/26/20e21ec873f41f2633703216453a44.png)

