当前位置: 首页 > news >正文

线程间共享数据

目录
  • 互斥量的锁定
  • 不仅仅是锁
    • 谨慎的设置接口
    • 初始化的保护
  • 死锁避免

互斥量的锁定

https://cppreference.cn/w/cpp/header/mutex
互斥量 std::mutex 不仅实现了互斥量的实例化,还提供了像 lock() 之类的成员函数来实现手动加锁和解锁。
但是实践中不推荐调用这些成员函数,而应该优先使用RAII风格的 std::lock_guardstd::unique_lock
这是因为如果线程在加锁后异常退出,锁资源不会被释放,有可能导致死锁。

#include <mutex>
#include <thread>
#include <iostream>
using namespace std;mutex mtx;
void dangerousFunction(int id) {mtx.lock();//线程2永远无法运行std::cout << "Thread " << id << " is running." << std::endl;if (id == 1) {throw std::runtime_error("Thread 1 encountered an error!");}mtx.unlock();
}
int main() {try {std::thread t1(dangerousFunction, 1);std::thread t2(dangerousFunction, 2);t1.join();t2.join();}catch (const std::exception& e) {std::cerr << "Exception caught: " << e.what() << std::endl;}return 0;
}

std::lock_guard 基于RAII实现,

  • 能够自动加锁,创建 std::lock_guard 对象时会自动加锁,如果互斥量已经被其他线程锁定,那么当前线程将会被阻塞,直到互斥量可用为止;
  • 自动解锁,在作用域结束时会自动释放互斥量;
  • 不支持手动加锁、解锁,不支持条件变量;
  • 禁止复制和移动;

std::unique_guard 相比 std::lock_guard 更加灵活,除了自动加锁、解锁外,它还支持:

  • 提供lock()和unlock(), 支持手动加锁、解锁:
  • 禁止复制,但支持移动语义,允许在不同作用域和函数间转移互斥量的所有权。;
  • 在构造对象时支持延迟加锁,支持尝试锁定;

std::unique_guard 虽然具有更强的性能但是也有更高的开销。

不仅仅是锁

谨慎的设置接口

在大多数情况下,互斥量通常会与保护的数据放在同一个类中,对其的操作声明为成员函数,这样就实现了封装和保护。而当其中一个成员函数返回的是保护数据的指针或引用时,就会破坏对数据的保护。具有访问能力的指针或引用可以访问(并可能修改)被保护的数据,而不会被锁限制。如果允许用户传入函数,那么需要确保用户不会保留指针或引用,但这很难保证,所以不推荐。

初始化的保护

假设有一个共享资源,只需要在初始化的时候进行保护,而后续的操作可能是只读的。而加载它的代价很大,常见的做法是在真正要使用这块数据时,才构造它(延迟初始化)。

std::shared_ptr<some_resource> resource_ptr;
std::mutex resource_mutex;void foo()
{std::unique_lock<std::mutex> lk(resource_mutex);  // 所有线程在此序列化 if(!resource_ptr){resource_ptr.reset(new some_resource);  // 只有初始化过程需要保护 }lk.unlock();resource_ptr->do_something();
}

如上的实现方法会降低程序执行的效率,因为即使共享数据已经初始化好,每次调用 foo() 函数,还是会锁定 resource_mutex,所有调用这个函数的线程,都会被不必要的串行化起来。
c++提供了 std::once_flagstd::call_once

std::shared_ptr<some_resource> resource_ptr;std::once_flag resource_flag; void init_resource(){resource_ptr.reset(new some_resource);}void foo(){std::call_once(resource_flag,init_resource); // 可以完整的进行一次初始化resource_ptr->do_something();}

死锁避免

  • 避免在持有锁时调用用户提供的代码;
  • 当要获取多个锁时:使用 std::lock 来一次获得多个锁;不能一次性获取,那么用固定的顺序获取;
http://www.sczhlp.com/news/71709/

相关文章:

  • 腾讯云服务器如何安装 zsh oh-my-zsh(解决 github 连接问题)
  • 【运维自动化-标准运维】各类全局变量使用说明(上)
  • 东铁匠营网站建设公司wordpress主题打不开
  • 职教集团网站建设方案政协系统网站建设
  • 中裕隆建设有限公司网站平面设计短期培训班
  • 别人不能注册我的wordpress站wordpress怎么给图片添加超链接
  • 网站维护升级页面wordpress用户个人资料
  • php网站开发技术论文iis做网站跳转
  • app开发网站wordpress搭建工单
  • 双井网站建设网站建设规划书感受
  • 计划出行到行程追踪,实况窗助力航旅纵横为用户打造“好用易用”的出行体验
  • 开源能源管理系统:能源转型时代的民主化革命
  • POD Out of memory heap
  • 做网站设计怎么进企业广州网站推广找谁
  • 网站怎么做全站搜索网站做qq微信微博登录
  • 简历电商网站开发经验介绍微信红包封面开放平台
  • 公司门户网站建设方案网站开发与管理专业的就业信息
  • 湘潭企业网站建设 磐石网络简单个人网页设计模板
  • 一笔成形,秒绘标准图!Pen Kit重构“自然书写”体验
  • 水利建设专项收入在什么网站上申报河南关键词优化搜索
  • 大学做视频网站设计wordpress阅读类主题
  • 青岛正规公司网站建设公司wordpress收录p
  • 怎么看网站是不是php语言做的广告发布是什么意思
  • 苏州高新区建设局网站管网黄骅港在哪里
  • 网站正在建设中敬请网站版块设计是什么意思
  • 网站建设流量是怎么回事科技类特长生有哪些项目
  • 可变参数
  • 字母异位词-leetcode
  • flask项目封装的flask-sqlalchemy的数据库连接池与自定义数据库连接池的项目
  • 哈尔滨建设网站哪家专业wordpress v4