笔记-线程安全的生命期管理
Posted 积少成多
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔记-线程安全的生命期管理相关的知识,希望对你有一定的参考价值。
- 当析构函数遇到多线程,当一个对象能被多个线程同时看到,那么对象的销毁时机就变得模糊不清了,可能出现多种竞争条件race condition:
- 在即将析构一个对象时,如何得知此刻是 否有别的线程正在执行该对象的成员函数
- 如何保证在执行成员函数期间,对象不会在另一个线程被析构
- 在调用某个对象的成员函数之前,如何得知这个对象还活着? 它的析构函数不会碰巧执行到一半?
- 记住share_ptr的用法.
- 线程安全:三个条件. 多个线程同时访问时,其表现出正确的行为;无论os如何调度这些线程,无论这些线程的执行顺序如何交织;调用端代码无须额外的同步或其他协调动作. 那么c++,标准库中的大多数class都不是线程安全的,包括std::string,vector,map,必须加深能够额外的锁才可以供多个线程同时访问.
- MutexLock/MutexLockGuard,自己实现的类. MutexLock,利用RAII收方封装互斥器的常见与销毁/临界区在windows上是struct CRITICAL_SECTION,是可重入的,而linux上的pthread_mutex_t默认是不可重入的. MutexLock一般是别的class的数据成员.;;;;;;;;MutexLockGuard封装临界区的进入和退出,即加锁和解锁.MutexLockGuard一般是栈上对象,作用域刚好等于临界区.
- 怎么样分析线程安全呢? 每个对象有自己的mutex_,因此不同对象之间不构成锁争用. mutex_ 成员是mutable的,意味着const成员函数如Counter::value也能直接使用non-const的mutex_.
class Counter : boost::noncopyable{ public: Counter():value_(0){} int value() const; int getAndIncrease(); private: int value_; mutable MutexLock mutex_; }; int Counter::value() const{ MutexLockGuard lock(mutex_);///lock的析构会晚育返回对象的构造 return value_; ///lock会在这里析构,作用域结束的时候,因此可以有效包括这个功效数据 } int Counter::getAndIncrease(){ MutexLockGuard lock(mutex_); int ret = value_++;///每个对象有自己的mutex_,因此不同对象之间不构成锁争用. return ret; }
- c++可能出现的内存有一下几个方面:
- 缓冲区溢出 buffer overrun
- 空悬指针/野指针
- 重复释放 double delete
- 内存泄露 memkory leak
- 不配对的new[]/delete
- 内存碎片 memory
正确使用智能指针share_ptr/weak_ptr解决前面的5个问题,
- 缓冲区溢出,用std::vector<char>/std::string或自己编写buffer class管理缓冲区,自动记住缓冲区的长度,公国成员函数而不是裸指针来修改缓冲区.
- 空悬指针/野指针,使用share_ptr/weak_ptr
- 重复释放,利用scopted_ptr,只在对象析构的时候释放一次
- 内存泄露:利用scopted_ptr,利利用
- 对象的创建, 要做到线程安全,唯一的要求就是在狗仔期间不要泄露this指针:
- 不要在构造函数中注册任何回调
- 也不要在构造函数中把this指针传递给跨线程的对象
- 即便在构造函数最后一行也不行
以上是关于笔记-线程安全的生命期管理的主要内容,如果未能解决你的问题,请参考以下文章
JAVA笔记(19)--- 线程概述;如何实现多线程并发;线程生命周期;Thread常用方法;终止线程的三种方式;线程安全问题;synchronized 实现同步线程模型;
[原创]java WEB学习笔记94:Hibernate学习之路---session 的管理,Session 对象的生命周期与本地线程绑定