waveInReset/waveOutReset死锁原因与解决方案
来源:互联网 发布:mac如何删除office 编辑:程序博客网 时间:2024/05/16 10:34
问题背景
录音播音实际需求
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都放到这个线程去处理,自然不会发生死锁了。
update by sld 2010-3-8
- waveInReset/waveOutReset死锁原因与解决方案
- 关于waveInReset/waveOutReset锁死问题
- GCD导致死锁的原因和解决方案
- 数据库死锁问题原因分析以及解决方案
- waveOutReset的N种死法, 及其解决方案
- 转:waveOutReset的N种死法, 及其解决方案
- waveOutReset的N种死法, 及其解决方案
- waveOutReset的N种死法, 及其解决方案
- 转载 waveOutReset的N种死法, 及其解决方案
- waveOutReset死法大全, 加解决方案
- 【转】waveOutReset的N种死法, 及其解决方案
- waveOutReset的N种死法, 及其解决方案
- oracle锁与死锁概念,阻塞产生的原因以及解决方案
- oracle锁与死锁概念,阻塞产生的原因以及解决方案
- oracle锁与死锁概念,阻塞产生的原因以及解决方案
- 线程发生死锁的条件与原因
- OC中GCD导致死锁的原因和解决方案
- 造成数据库表死锁的原因分析及解决方案
- Java调用Linux命令
- poj 1657
- 2010 小玩股票的进
- java--各种数据库连接jdbc
- 最近翻译的ISAPI_Rewrite中文手册7
- waveInReset/waveOutReset死锁原因与解决方案
- log4j 配置祥解
- Java类中热替换的概念、设计与实现
- 人生的Exception
- 换了家公司,接触嵌入式~~
- mysql中的SQL分析工具
- 从西天取经事件看官场潜规则
- configure: error: Can not link to python
- hdu1201 算日子