线程安全的对象生命周期管理
析构遇见多线程
-
会出现竟态条件
- 一个线程调用析构函数时,有没有其他线程调用该对象的其他函数
- 如果一个对象的函数正在执行,对象是否被其他线程析构
- 怎么保证该对象是否存活。如果析构执行一半呢?
-
线程安全的定义
- 多线程下可以保证正确的行为
- 无论系统怎么调用线程
- 在写代码的时候不需要额外的同步手段
-
一个简单的例子
-
class Counter{ private: int64_t value_; mutable MutexLock mutex_; }; -
这个类是线程安全的,每个对象都有自己的锁,不会有竟态条件
-
通过动态创建的对象,就是new出来的对象,通过指针访问还会有竟态条件
- 两个线程A和B,通过指针访问堆上的对象
- 线程A想要通过指针访问该对象,线程B通过指针想要释放该对象
- 线程A拿到了该对象,此刻立即切换到B线程,线程A的操作就危险了
- 即使释放对象后将指针置空也无法解决
-
-
在构造函数里面不能泄漏this指针
- 在观察者模式里面
-
class Foo : public Observer { public: Foo(Observable* s) { s->register_(this); // 错误,非线程安全 //可能还会有其他操作 } virtual void update(); }; - 在构造函数里面进行注册行为,但是对象还没构造完成,这个this是一个半成品,其他线程拿到后会很危险
-
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);