【Linux多线程服务端编程】| 【02】线程同步精要

索引

【Linux多线程服务端编程】| 【01】线程安全的对象生命期管理笔记
【Linux多线程服务端编程】| 【02】线程同步精要
【Linux多线程服务端编程】| 【03】多线程服务器的适用场合和常用编程模型
【Linux多线程服务端编程】| 【04】C++多线程系统编程精要

在这里插入图片描述

线程同步

1 互斥器 Mutex

【C++模块实现】| 【07】对于互斥、自旋锁、条件变量、信号量简介及封装
最常用,保存临界区,任何时刻最多只能由一个线程在此mutex划出的临界区内活动;
【RAII封装mutex】:

  • 只用不可重入
  • 不手工调用上锁、解锁;
  • 可以防止加锁顺序不同而导致死锁;

【次要原则】:

  • 不适用跨进程的mutex,进程间通信只用在TCP sockets
  • 加锁、解锁在同一线程,其他线程不能去解其他线程的锁;
  • 必要时候使用PTHREAD_MUTEX_ERRORCHECK
1.1 只使用不可重入的mutex

【可重入和不可重入的区别】:

  • 同一线程可重复对重入加锁,不能对非重入加锁;
  • 两者性能相差不大,只是少用一个计数器
  • 在同一线程对非重入加锁会立刻导致死锁,能在调试中暴露问题;
  • 可重入可能会在代码中隐藏问题;

【可重入问题】:
在这里插入图片描述

  • 若mutex为不可重入,则死锁
  • 若mutex为可重入,则push_back可能导致vector迭代器失效,程序可能会瘫痪;

【若确实需要修改vector】:

  • 可将修改推后先记录循环中要添加或删除的元素,循环结束后在修改;
  • 或使用copy-on-write后续介绍;

【建议】:若一个函数可能会在加锁或不加锁的情况下使用

  • 定义一个跟原来一样的同名函数
  • 但容易误用倒是死锁或数据损坏;
    在这里插入图片描述
    【在该函数上如何避免死锁或数据损坏】:
  • 【死锁】:后续;
  • 【数据损坏】:在postWithLockHold加上assert,判断是否上锁;
1.2 死锁

【死锁中如何调试】:
https://www.cnblogs.com/zhuyp1015/p/3618863.html
【示例】:
在这里插入图片描述
在这里插入图片描述

【两个线程死锁】:
在这里插入图片描述
Inventory中的printAll可能回引发死锁;
【原由】:Inventory::printAll(#6)调用Inventory::printAll(#5)…而调用threadFunc线程先调用Request::~Request(#6)在调用Inventory::remove(#5);两个序列加锁顺序相反导致的;

在这里插入图片描述

2 条件变量

mutex是用来排他性地访问共享数据,不是等待原语

若需要等待某条件成立,则需要使用条件变量

【wait】:

  • 必须与mutex使用,让条件读写受mutex保护
  • 在mutex已上锁时才能调用wait,避免出现虚假唤醒
  • 需要将条件和wait()置入while中;

在这里插入图片描述

【signal、broadcast】:

  • 不一定要在mutex已上锁的情况下调用signal
  • 在signal前要修改条件变量
  • 修饰条件变量要用mutex保护;
  • 注意区分signal(为资源可用)boradcast(为明状态变化);

在这里插入图片描述

【倒计时,同步用途】:

  • 用于主线程等待子线程完成初始化(子线程完成一定任务后,主线程才执行);
  • 多个子线程等待主线程发出起跑命令
  • 接口使用简单;
    在这里插入图片描述

3 不要用读写锁和信号量

【读写锁容易错误】:

  • 容易在有读锁时修改了共享数据
  • 读写锁不见得比mutex更高效,由于读锁需要更新当前reader的数目;
  • 一般锁时可重入写锁不可重入,为了预防写饥饿,写锁一般回阻塞后来的读锁,而读锁是可重入,会导致死锁;
  • 若对并发有极高性能,可考虑使用read-copy-update

【信号量】:需要维护计数值

  • 在维护的同时,回造成同样的两份数据,保持一直,易出错增加负担;

4 封装Mutex

该类class不允许拷贝构造赋值

【Mutex封装】:

请添加图片描述

MutexLockGuard(x)是为了防止错误使用;

在这里插入图片描述

【条件变量封装】:
在这里插入图片描述

存在mutex和条件变量,需要注意他的声明、初始化顺序

在这里插入图片描述

5 线程安全的Singleton实现

在此之前,提出过double checked locking来解决单例问题,但还是有缺陷,可用使用pthread_once
在这里插入图片描述

使用pthread_once_t来保证lazy initialization的线程安全,可使用atexit来提供销毁功能;

6 sleep(3)不是同步原语

生产中的线程等待:

  • 等待资源可用select/poll/epoll_wait条件变量上;
  • 等待进入临界区以便读写共享数据;

若在等待某个事件要发生,一般采用select等或条件或线程池、倒计时、队列,而不是使用sleep;

7 借助shared_ptr实现copy-on-write

主要解决读多写少的场景,当一个函数在读取时,我们对列表进行写入或删除操作可能会引起不必要的麻烦,所以在写入时,我们应该在拷贝一个副本在副本上进行操作;

在这里插入图片描述

【原理】:

  • write,若发生引用计数为1,则可安全修改共享
  • read,在读前把引用计数加1,读完后减1保证读期间引用计数大于1,来阻止并发写
  • 主要:当write引用计数大于1,该如何解决;

【以下为解决1.1内容中的问题】
在这里插入图片描述

【解决1.2问题】

  • 【做法一】:先将数据拷贝,在对齐进行遍历

在这里插入图片描述

  • 【做法二】:用shared_ptr管理set,遍历时增加引用计数,阻止并发并修改;copy-on-write

【用mutex替换读写锁的场景】:

当有几个工作线程处理客户交易请求(只读),另一个协程确保数据更新map(读写),

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jxiepc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值