Linux多线程服务器 ---- 线程安全的对象生命周期管理

本文探讨了C++多线程环境下线程安全对象的构造与销毁问题,重点介绍了如何利用Boost库中的shared_ptr与weak_ptr解决对象析构时可能出现的竞态条件,确保线程安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
编写线程安全的类不难,用同步语句保护内部状态即可。但是对象的生死不能由对象自身拥有的mutex来保护

–>在c++多线程编程时如何避免对象析构时可能存在的race condition???

–>这篇文章将使用Boost库中的shared_ptr与weak_ptr来解决这个问题。


当一个对象能够被多个线程同时看到,那么此对象的销毁就会变得模糊不定。可能会有几种问题出现:

  • 如何保证执行成员函数时,对象不会在另一个线程中被析构???
  • 在析构一个对象的时候,如何知道此刻是否有其他线程正在执行该对象的成员函数???
  • 在调用对象的成员函数的之前,如何得知此对象是否活着???

1、创建线程安全的对象

对象构造若想做到线程安全,唯一的要求构造期间不要暴露this指针,也就是:

  • 不要在构造函数中注册回调
  • 不要在构造函数中把this传给跨线程的对象
为什么这么做??

在构造函数执行期间对象还没有完成初始化,如果this被泄漏给了其他对象,那么别的线程有可能访问这个半成品对象,会引起严重后果。也就是必须保证构造函数完全执行完才被调用

那么怎么正确的进行对象构造??

在多线程下,我们采用二段式构造的方法。

2、探索如何进行对象销毁

2.1 mutex不行

mutex只能保证函数一个接一个的执行,如果试图用mutex去保护析构函数:

Foo::~Foo()
{
    MutexLockGuard lock(mutex_);

}
void Foo::update()
{
    MutexLockGuard lock(mutex_);  //(1)
}

//Thead A
delete x;
x = NULL;
//Thread B
if(x){
	s->update();
}

此时线程A即将销毁x,线程B则正准备调用x->update()。此时就会出现一种竞争:当A执行到析构函数处,此时拿到了互斥锁,即继续向下执行,线程B 通过了if条件,阻塞在(1)处;那么接下来因为析构函数把mutex_销毁,那么update里面就可能一直阻塞(1)处或者发生其他更坏的情况;

====》作为数据成员的mutex不能够保护析构函数


2.2 如何知道动态创建的对象是否存活

对于动态创建的对象,光看指针是不能看出其状态。指针指向一块内存,这块内存上的对象如果已经销毁,那么根本就不能访问,不能访问怎么去知道对象的状态呢??(万一原址又创建了一个新的对象呢?)

举个例子:对象a 、 b,a持有b的指针,b的生命周期不由a单独控制,此时如果b是动态创建并且在程序结束前有可能被释放,那么就会出现竞态。。。

----解决方法1(此方法不好)》那么好像可以用对象池来解决这个例子出现的问题:只创建不销毁

完美解决方法探索

为了知道对象的状态,进行接下来的操作:
1)引入间接性
引入间接性,让p1与p2永久有效。当销毁p1时,p2也不会变成空悬指针,可以通过proxy内的内容来判断object是否存活。
在这里插入图片描述
但是,何时释放proxy呢??????

2)引入计数器
为了释放proxy,我们引入计数器,开始p1、p2指向pointer,计数器初始值为2;p1析构了,计数器count变为1;当计数器降为0时,释放pointer。
在这里插入图片描述

这不就是shared_ptr吗。

3)使用shared_ptr / weak_ptr完美解决

  • shared_ptr控制对象的生命周期。shared_ptr是强引用,只要有一个对象的shared_ptr存在,该x对象就不会被析构。
  • weak_ptr不控制对象的生命周期。但是它知道对象是否活着,如果对象活着,那么它进化为有效的shared_ptr;如果对象死了,进化失败,返回一个空的shared_ptr;

参考书籍:《Linux多线程服务器端编程》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值