目录
1.前言
2.正文
3.代码和验证
1.前言:前几日上班时,因为底层逻辑修改。多线程情况下,许多函数如果依然按照原有的锁去串行执行,效率会很低。(原先是 std::mutex ,以及每个函数用的锁是std::lock_guard)
这时我的领导给我新任务,修改多线程的锁,在修改后,要求函数 1 函数2 要能并发执行,且前两者并发执行时与函数 3 函数4 函数5是互斥的。而函数 3,4,5与所有函数都互斥。(例如函数3运行的时候,函数1 2 4 5都是卡着等待函数3执行完毕再继续执行)。
我实在是不会做,这个时候请教我领导,他告诉我用读写锁就能解决问题。c++读写锁的应用也就是使用 shared_mutex,shared_lock,这两者者解决问题。
这是本人对此次经历的记录,可能写的并不太好。可以参考他人文章和cppRefrecne官方文章。
C++多线程——读写锁shared_lock/shared_mutex_princeteng的博客-CSDN博客_shared_lock
std::shared_lock - cppreference.com
2.正文:关于shared_mutex,shared_lock的知识和描述shared_mutex?类是一个同步原语,可用于保护共享数据不被多个线程同时访问。与便于独占访问的其他互斥类型不同,shared_mutex 拥有二个访问级别:
共享?- 多个线程能共享同一互斥的所有权。 独占性?- 仅一个线程能占有互斥。若一个线程已获取独占性锁(通过?lock?、?try_lock?),则无其他线程能获取该锁(包括共享的)。
仅当任何线程均未获取独占性锁时,共享锁能被多个线程获取(通过?lock_shared?、?try_lock_shared?)。
在一个线程内,同一时刻只能获取一个锁(共享或独占性)。
共享互斥体在能由任何数量的线程同时读共享数据,但一个线程只能在无其他线程同时读写时写同一数据时特别有用。
shared_mutex?类满足共享互斥体?(SharedMutex)?和标准布局类型?(StandardLayoutType)?的所有要求。
以上是cppreferenced的原文。翻译一遍就是这样的逻辑
当Mutex是shared_mutex?的时候
1.当有函数使用共享锁时,能够与其他享有共享锁的函数也能并发同步执行。而和所有独占锁的函数是互斥的。
2.当有一个函数使用独占锁时,其他所有的用同一个Mutex带锁的函数都是与其互斥的。
那么这个情况就和我所遇到的需求是完全一致的。
已知的独占锁
已知的共享锁
以下代码是本人在vs2019,c++最新标准下运行的。
可以直接复制过去看效果,也可以自己稍作修改进行验证
#include <iostream> #include <string> #include <mutex> #include <thread> #include <shared_mutex> #include <Windows.h> std::shared_mutex g_sMutex; void writeTime(const std::string funName ,int time) { for (size_t i = 1; i < time; i++) { std::string outPut = funName + ":" + std::to_string(time); std::cout << outPut << std::endl; Sleep(1000); } } void shared_1(int seconds) { std::shared_lock<std::shared_mutex> theLock(g_sMutex); writeTime("shared_1" , seconds); } void shared_2(int seconds) { std::shared_lock<std::shared_mutex> theLock(g_sMutex); writeTime("shared_2", seconds); } void unique_1(int seconds) { std::unique_lock<std::shared_mutex> lck(g_sMutex); writeTime("unique_1", seconds); } void unique_2(int seconds) { std::unique_lock<std::shared_mutex> lck(g_sMutex); writeTime("unique_2", seconds); } void nomralSuo(int seconds) { std::lock_guard<std::shared_mutex> lck(g_sMutex); writeTime("nomralSuo", seconds); } int main() { std::vector<std::thread> vecThread; vecThread.push_back(std::thread(nomralSuo, 10)); vecThread.push_back(std::thread(shared_1, 10)); vecThread.push_back(std::thread(shared_2, 10)); vecThread.push_back(std::thread(unique_1, 10)); vecThread.push_back(std::thread(unique_2, 10)); for (auto & oneThread : vecThread) { oneThread.join(); } }
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。 |