waveInReset/waveOutReset死锁原因与解决方案

简介:

问题背景

 

录音播音实际需求

1、随时终止

2、录音并非文件,而是形成rtp发送

3、播音并非源于文件,而是源于rtp

 

因此Waveform audio使用的buffer较小,不断的装载/发送 buffer,终止的时候Reset并且close.

大致如下调用的循环

 

录音

waveInUnprepareHeader

waveInPrepareHeader

waveInAddBuffer

 

播音

waveOutUnprepareHeader

waveOutPrepareHeader

waveOutWrite

 

循环周期40ms,我采用的是回调函数。问题是有时候调用waveInReset/waveOutReset会形成死锁,调用waveInReset/waveOutReset的线程与回调函数所在的线程死锁在一块了。

 

原因分析

这方面网上有文章提到,就是调用waveInReset/waveOutReset的同时调用了录音/播音循环调用的某个函数会形成死锁。我再稍作解释下,我们知道buffer满了或是调用Reset都会触发消息(回调函数方式的话就是MM_WOM_DONE/MM_WIM_DATA),由于调用waveInReset/waveOutReset所在的线程,与回调函数所在的线程不是一个线程,因此很容易撞车,也就是说,你调用reset的时候,另一个线程正好在处理MM_WOM_DONE/MM_WIM_DATA,于是就这样死锁了。

 

解决方案

方案一

先加上标记(假设标记bReset:bool),令bReset为true;

 

标记作用如下

if(!bReset)

{

录音

waveInUnprepareHeader

waveInPrepareHeader

waveInAddBuffer

 

播音

waveOutUnprepareHeader

waveOutPrepareHeader

waveOutWrite

}

延时调用waveInReset/waveOutReset,延时时间长度以循环周期为妙,我这个例子中也就是采用40ms。

 

当然也可以采用临界保护。


方案二

换一个角度去考虑问题,之所以死锁,是因为两个线程冲突了的缘故,所以可以建立一个线程

录音

waveInUnprepareHeader

waveInPrepareHeader

waveInAddBuffer

 

播音

waveOutUnprepareHeader

waveOutPrepareHeader

waveOutWrite

 

与waveInReset/waveOutReset都放到这个线程去处理,自然不会发生死锁了。

目录
相关文章
|
8月前
关于死锁的原因及解决方案
关于死锁的原因及解决方案
92 0
|
3月前
|
算法
死锁的一点分析
死锁的一点分析
多线程之探讨死锁的成因和解决方案
多线程之探讨死锁的成因和解决方案
多线程之探讨死锁的成因和解决方案
|
4月前
|
Java 调度
没了解死锁怎么能行?进来看看,一文带你拿下死锁产生的原因、死锁的解决方案。
没了解死锁怎么能行?进来看看,一文带你拿下死锁产生的原因、死锁的解决方案。
23 0
|
9月前
什么是死锁?产生死锁的原因?产生死锁的四个必要条件?死锁的避免与预防?
什么是死锁?产生死锁的原因?产生死锁的四个必要条件?死锁的避免与预防?
157 0
|
4月前
|
前端开发 JavaScript
竞态问题:深入理解与解决方案
竞态问题:深入理解与解决方案
|
8月前
|
设计模式
【并发技术04】线程技术之死锁问题
【并发技术04】线程技术之死锁问题
|
12月前
死锁的成因和对应的解决方案
死锁的成因和对应的解决方案
|
调度
死锁的四个必要条件及避免策略
死锁的四个必要条件及避免策略
255 0
死锁的四个必要条件及避免策略
|
NoSQL Redis 开发者
事务-死锁解决方案|学习笔记
快速学习事务-死锁解决方案
89 0

热门文章

最新文章

相关实验场景

更多