Android C++多线程按顺序退出并释放资源

本文介绍FFmpeg解码多线程流程,并提供安全退出多线程的方法,包括使用pthread_join函数确保资源安全回收。

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

我的视频课程(编码直播推流):《Android视频编码和直播推流》

我的视频课程(C++ OpenGL):《Android C++ OpenGL教程》

        通过这段时间的加班,终于把我的FFmpeg开发课程《FFmpeg打造Android万能音频播放器》和《FFmpeg+OpenGL ES+OpenSL ES打造Android视频播放器》录制完成了。在开发过程中涉及到了许多的知识点,其中一个就是C++多线程解码退出问题,今天我们就来讲讲怎样按顺序退出多线程。

一、引出问题

        首先我们来看一下FFmpeg解码多线程流程图:

从图中我们看到了至少得用3个线程来解码视频:

第一个是:FFmpeg的解码线程

第二个是:音频播放线程

第三个是:视频播放线程

并且,这3个线程都是在while循环中执行的,因此当我们想停止播放时问题就来了:我们需要分别停止这3个线程并回收线程资源,而这3个线程也有共同的操作对象。当线程还在执行时我们就回收资源的话(因为线程中有sleep操作,不能保证在回收资源钱线程就退出了),就会导致还在执行的线程调用资源时出现错误的地址访问,导致崩溃现象,这是多线程中经常出现的一个问题。

二、解决方案

为了解决上面的问题,我们最理想的就是:在回收资源之前,需要把所有访问资源的线程给停止掉,然后就可以放心的回收资源了。那么解决的办法也有许多:

第一种:就在线程的最后直接回收资源,只要线程结束,就回收资源,如:

第二种:添加变量来判断线程是否退出,回收资源前循环判断此变量,知道线程退出后才回收资源,如:

第三种:使用pthread_join(thread, void**)函数,这个函数会阻塞当前线程,直到目标线程退出后才往下执行。这就是最完美的等待线程退出的方法。

三、实现过程

在回收资源之前,调用pthread_join函数阻塞当前线程,等待目标线程退出后才回收资源,这样就能保证回收的资源时没有被使用的:

这样就能完美的解决多线程退出问题了,我们还可以指定退出顺序,完全按照自己的想法退出,就能很好地解决我们的问题了。

四、实例代码

这里我写了一个模拟多线程解码的demo,详细代码我就不贴出来了,文末有实例下载地址,可以自行下载运行。

4.1 未添加线程控制pthread_join函数时效果:

我们发现,资源已经回收之后,而音频或视频的解码线程还在解码,这样就会导致方法资源地址错误。

4.2 使用线程控制pthread_join函数时效果:

从上面打印日志可以看出,都是先退出线程后回收资源,这样就能保证多线程退出的安全性了。

五、总结

FFmpeg解码音视频算是很复杂的了,里面牵扯太多知识点。但是任何复杂的功能,都是有一个个功能(知识点)组合而来的,只有当我们把这些知识点理解透彻之后,才能写出健壮而复杂的程序出来,最后来一张我视频课程里面的效果图:

 

好了,就到这里吧,实例下载地址:

GitHub地址:C++多线程退出并释放资源

 

### Dumkey Sharp C++ 序打开后立即退出的原因分析 序在启动后立即退出可能是由多种因素引起的。以下是可能导致该问题的主要原因及其对应的解决方案: #### 1. 主线程未正确处理 如果序的主线程未能保持活动状态,则会在完成初始化操作后自动终止。这通常是由于缺少循环机制来维持序运行所致。 ```cpp // 示例代码:确保主线程持续运行 #include <iostream> int main() { std::cout << "Program is running..." << std::endl; while (true) { } // 防止序立即退出 return 0; } ``` 这种情况下,可以引入事件驱动模型或使用 `std::cin.get()` 来等待用户输入[^1]。 --- #### 2. 子线程未被妥善管理 如果有托管线程(非主线程)存在,但在主线程结束前这些子线程尚未完成执行,也可能导致序异常退出。这是因为某些操作系统会强制销毁所有附属线程。 ```cpp // 示例代码:确保子线程安全退出 #include <thread> void threadFunction() { std::this_thread::sleep_for(std::chrono::seconds(5)); } int main() { std::thread t(threadFunction); t.join(); // 等待子线程完成后再退出 return 0; } ``` 通过显式调用 `join` 或设置标志位控制线程生命周期,可有效防止此类问题发生。 --- #### 3. DLL 文件加载失败 当序依赖于外部动态链接库(如 SHCore.DLL),而目标系统上缺失必要文件或者版本不匹配时,也会引发崩溃行为。具体表现为尝试访问不存在的功能入口点。 > **注意**: 如果错误提示与 shcore.dll 相关,则需确认其是否存在以及是否损坏[^3]。 修复方法包括重新安装相关组件、更新 Windows 更新补丁包或将所需 dll 复制到应用目录下。 --- #### 4. 资源释放不当 对于图像处理类项目而言,若忘记清理分配给 OpenCV 的内存空间,在 Android 平台上尤其容易造成不可预期的结果[^5]。因此建议每次读取帧之后都及时释放不再使用的对象实例。 ```cpp cv::Mat frame; if (!cap.read(frame)) break; // 检查视频流有效性 frame.release(); ``` 上述片段展示了如何优雅地停止捕获过回收资源。 --- #### 5. 调试工具集成不足 尽管 C# 提供了良好的跨平台调试体验[^4],但对于原生 C++ 应用来说,仍有必要借助专门的日志记录框架定位潜在缺陷位置。例如 Google Logging Library(glog),可以帮助开发者快速发现逻辑漏洞所在之处。 --- ### 综合解决方案 针对以上提到的各种可能性逐一排查即可找到根本原因。推荐按照如下顺序开展工作: - 添加日志打印语句以便观察流走向; - 审核多线程部分是否有遗漏同步措施的地方; - 测试不同环境下能否稳定运作从而缩小范围至特定硬件/软件组合间差异方面考虑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ywl5320

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值