You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

对象动态变量被mutex锁定时析构函数是否无法释放内存?分离线程场景下mutex的使用正确性咨询

多线程异步场景下的内存安全与Mutex使用问题

先来看你给出的核心代码和测试场景:

基础对象定义

#include <thread>
#include <mutex>
using namespace std;
mutex mu;
class Object {
public:
 char *var;
 Object() {
 var = new char[1];
 var[0] = 1;
 }
 ~Object() {
 mu.lock();
 delete[]var; // 析构函数确实需要释放自身持有的动态内存
 mu.unlock();
 }
}*object = nullptr;

测试用的多线程代码

void do_something() {
 for(;;) {
 mu.lock();
 if(object)
 if(object->var[0] < 255)
 object->var[0]++;
 else
 object->var[0] = 0;
 mu.unlock();
 }
}
int main() {
 object = new Object();
 thread th(do_something);
 th.detach();
 Sleep(1000);
 delete object;
 object = nullptr;
 return 0;
}

接下来逐个解答你的疑问:


1. 是否存在var无法被析构函数释放的可能?

不会。只要delete object;被执行到,Object的析构函数就一定会被调用,而析构函数里的delete[] var;也会正常释放这块动态内存。不过要注意:如果主线程delete object之后,分离线程还在尝试访问object->var,这会触发未定义行为(比如程序崩溃、内存乱码),但var本身的释放操作是能完成的。

2. 分离线程里使用mutex的方式是否正确?

逻辑方向是对的,但有个可以优化的点:手动调用lock()和unlock()容易因为代码变更或者异常(虽然这里没有异常场景)导致锁无法释放,更推荐用RAII风格的锁管理类,比如std::lock_guard,它会在构造时自动加锁,离开作用域时自动解锁,代码更简洁安全:

void do_something() {
 for(;;) {
 lock_guard<mutex> guard(mu); // 自动管理锁的生命周期
 if(object) {
 if(object->var[0] < 255)
 object->var[0]++;
 else
 object->var[0] = 0;
 }
 }
}

2.1 是否需要用mutex包裹delete object语句?

必须要! 你当前的代码里,主线程delete object时没有加锁,极大概率会出现竞态条件:比如分离线程刚拿到锁,进入if(object)判断为真,还没来得及访问var,主线程就把object删除并设为nullptr了,这时候分离线程再访问object->var就是在操作一个野指针,直接触发未定义行为。

正确的做法是给主线程的delete操作也加上锁:

int main() {
 object = new Object();
 thread th(do_something);
 th.detach();
 Sleep(1000);
 
 // 加锁保护object的销毁操作
 mu.lock();
 delete object;
 object = nullptr;
 mu.unlock();
 
 return 0;
}

这样就能保证,主线程销毁object的时候,分离线程要么在等待锁,要么已经完成了一轮访问并释放了锁,不会出现中间状态的非法访问。


关于Mutex的核心理解补充

你后来对Mutex的理解完全正确:它本质就是一个带有“锁定状态”的同步工具,核心作用是保证同一时间只有一个线程能进入临界区。用普通bool变量模拟的话,会因为线程切换的不确定性导致竞态条件(比如两个线程同时看到bool为false,都进入临界区),而Mutex的lock/unlock是原子操作,由操作系统底层支持,能彻底避免这种问题。

至于你最后问的「为什么多线程访问mutex本身不会导致未定义行为?」——因为Mutex的设计就是线程安全的!它的所有公开方法(lock、unlock、try_lock等)都是原子实现的,操作系统会保证多个线程对同一个Mutex对象的操作是有序且安全的,不会出现竞态条件,这也是它能用来做线程同步的核心原因。

内容的提问来源于stack exchange,提问作者Ngdgvcb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 17:17:28