学习muduo网络库笔记

27 阅读2分钟

线程安全的对象生命周期管理

析构遇见多线程

  • 会出现竟态条件

    1. 一个线程调用析构函数时,有没有其他线程调用该对象的其他函数
    2. 如果一个对象的函数正在执行,对象是否被其他线程析构
    3. 怎么保证该对象是否存活。如果析构执行一半呢?
  • 线程安全的定义

    1. 多线程下可以保证正确的行为
    2. 无论系统怎么调用线程
    3. 在写代码的时候不需要额外的同步手段
  • 一个简单的例子

    1.  class Counter{
       private:
       int64_t value_;
        mutable MutexLock mutex_;
       };
      
    2. 这个类是线程安全的,每个对象都有自己的锁,不会有竟态条件

    3. 通过动态创建的对象,就是new出来的对象,通过指针访问还会有竟态条件

      • 两个线程A和B,通过指针访问堆上的对象
      • 线程A想要通过指针访问该对象,线程B通过指针想要释放该对象
      • 线程A拿到了该对象,此刻立即切换到B线程,线程A的操作就危险了
      • 即使释放对象后将指针置空也无法解决
  • 在构造函数里面不能泄漏this指针

    1. 在观察者模式里面
    2.  class Foo : public Observer 
       {
       public:
       Foo(Observable* s)
       {
           s->register_(this); // 错误,非线程安全
           //可能还会有其他操作
       }
       virtual void update();
       };
      
    3. 在构造函数里面进行注册行为,但是对象还没构造完成,这个this是一个半成品,其他线程拿到后会很危险
    4.  class Foo : public Observer
       {
       public:
       Foo();
       virtual void update();
       // 另外定义一个函数,在构造之后执行回调函数的注册工作
       void observe(Observable* s)
       {
       s->register_(this);
       }
       };
       Foo* pFoo = new Foo;
       Observable* s = getSubject();
       pFoo->observe(s); // 二段式构造,或者直接写s->register_(pFoo);