zoukankan      html  css  js  c++  java
  • C++怎么实现线程安全

    muduo库学习笔记1-C++多线程系统编程

    • 网上都说这本书很适合初学者入门学习, 我今天开始准备从头再来;

    第一章线程安全的对象管理

    • 对象的生与死不能由对象自身拥有的mutex(互斥器)来保护;
    • 如何避免对象析构时可能存在的race conditon(竞态条件)是C++多线程编程面临的基本问题, C++借用shared_ptr和weak_ptr完美解决;
    • shared_ptr和weak_ptr是实现线程安全的Observer设计模式的必备技术;
    当析构函数遇到多线程
    • C++要求程序员自己管理对象的生命期, 这在多线程环境下显得尤为困难; 因为析构的时候会出现一些问题:
      • 在即将析构一个对象时, 怎么知道其他线程正在使用该对象的成员函数;
      • 如何保证我在使用一个对象的时候, 没有其他线程来析构这个对象;
      • 调用一个对象之前, 如何知道这个对象还活着, 它的析构函数会不会碰巧执行到一半?
        • 可以简单的通过shared_ptr进行一劳永逸的解决这些问题;
    • 什么是线程安全?
      • 一个线程安全的类(class)应当满足三个条件:
        • 多个线程同时访问时, 其表现出正确的行为;
        • 无论操作系统如何调度这些线程, 无论这些线程的执行顺序如何交织(interleaving);
        • 调用端的代码无需额外的同步或其他协调动作;
    • 锁的封装都可以进行临界区的处理(Critical section) -- 也就是把加锁放在构造函数, 把解锁放在析构函数, 这样就可以只加锁, 不管解锁就好了;
    对象的创建很简单
    • 对此昂的构造要做到线程安全, 唯一的要求是在构造起见不要泄露this指针;
      • 不要在构造函数中注册任何回调;
      • 也不要在构造函数把this指针传给跨线程的对象;
      • 几遍在构造函数的最后一行也不行;
      • 如果this指针被泄漏给其他对象, 可能是一个半成品;
    互斥变量的销毁太难
    • 因为析构函数中会把mutex销毁;
    • 作为成员的mutex不能保护析构
    • 一个函数如果要锁住相同类型的多个对象, 为了保证始终按相同的顺序加锁, 我们可以比较mutex对象的地址, 始终加锁地址较小的;
    • 对象的三种关系: composition(组合), aggregation(聚合), association(关联);
    • 解决空悬指针的办法是引入一层间接层, 更好的方法是使用引用计数;

    神器shared_ptr/weak_ptr

    • shared_ptr是引用计数型智能指针;
      • 引用计数为0, 自动销毁;
    • weak_ptr也是一个引用计数型智能指针, 但它不增加对象的引用计数, 即弱引用(weak);
    • C++的内存问题大致有这么几个方面:
      • 缓冲区溢出(buffer overrun);
      • 空悬指针/野指针;
      • 重复释放(double delete);
      • 内存泄漏(memory leek);
      • 不配对的new[]/delete;
      • 内存碎片(memory fragmetation);
    • scoped_ptr/shared_ptr/weak_ptr都是值语意;
    • 多线程访问同一个shared_ptr, 正确的做法是用mutex保护;
    • shared_ptr技术与陷阱;
      • 意外延长水箱的生命周期: shared_ptr是强引用, 只要有一个指向x对象的shared_ptr存在, 该对象就不会析构;
      • shared_ptr拷贝开销比原始指针高;
      • 析构函数在创建时被捕获;
      • 现成的RAII handle, RAII(资源获取即初始化)是C++语言区别于其他所有编程语言的最重要的特性, 一个不懂RAII的C++程序员不是一个合格的C++程序员;
      • shared_ptr是管理共享资源的利器, 需要注意避免循环引用, 通常的做法是owner持有指向child的shared_ptr, child持有指向owner的weak_ptr;

    对象池

    • 如果对象还活着, 就调用它的成员函数, 否则忽略它;
    • 用流水线, 生产者消费者, 任务队列这些有规律的机制, 最低限度地共享数据;
  • 相关阅读:
    Oracle错误一览表
    CAP原理
    阿里巴巴供应链平台事业部2020届秋招-Java工程师
    IM即时通信软件设计
    邮箱核心业务领域建模
    DDD中的聚合和UML中的聚合以及组合的关系
    对关系建模
    DDD战略设计相关核心概念的理解
    DDD领域建模基本流程
    谈谈Paxos一致性算法和一致性这个名词
  • 原文地址:https://www.cnblogs.com/longjiang-uestc/p/9644846.html
Copyright © 2011-2022 走看看