好的,你明白我会解释这个问题: 我正在使用一个名为ClanLIB的库(不是我的选择),该库,SEEMLY(我不确定,甚至读取sourcE),创建一个处理声音的线程。
当缓冲区为空时,此线程尝试获取更多数据,通常这会导致数据生成库太慢而无法在声卡到达缓冲区之前提供更多数据时出现欠载。
所以我添加了自己的线程,在后台继续产生声音。
这很好用,除了我自己的线程有时会劫持太多CPU时间并冻结其他所有内容。为了解决这个问题,我添加了条件等待。
当缓冲区已满时发生条件等待,当ClanLIB请求更多数据时,将发出等待信号,从而恢复缓冲区写入线程(直到它再次满为止)。
我的问题是,因为我添加了这个条件等待,ClanLIB声音线程和我自己的音乐线程,SOMETIMES变得“失控”,播放音乐,而应用程序的其余部分冻结。
会导致什么样的奇怪情况?
伪代码:
//main thread (that get frozen)
start_sound_thread();
do_lots_of_stuff();
quit();
//Sound Thread:
While(true)
{
play(buffer);
if(buffer_empty)
{
mutex.lock()
buffer = buffer2;
if(buffer2_full)
{
signal(cond1);
buffer2_full = false;
}
mutex.unlock()
}
}
//Music Library Thread:
while(true)
{
mutex.lock()
if( check_free_space(buffer2) == 0)
{
buffer2_full = true;
condition_wait(cond1);
}
write_music(buffer2);
mutex.unlock()
}
答案 0 :(得分:1)
你在互斥区域内做得太多了 - 很可能你在cond1信号上陷入僵局。你应该在锁定区域内尽可能少地做,因为你做的越多,引入死锁的风险就越大 - 你绝对不应该等待保护信号发送的互斥锁内部的信号 - 如果你'等待,它永远不会被发送 - condition_wait没有解锁你的互斥对象,它怎么能知道呢?
'通过添加条件等待解决'是一个强有力的指标,你已经遇到了导致死锁的竞争条件 - 一旦逻辑的执行时间因任何原因发生变化,你就没有解决问题,比如说因为另一个应用程序正在运行,死锁可以返回。
答案 1 :(得分:1)
我也在使用clanlib进行项目,但是使用OpenAL进行声音处理。它似乎与提供缓冲区等工作方式相同。
我也使用单独的线程来获取声音,但我的解决方案是在每次尝试输入缓冲区后添加一个固定的睡眠周期。这很简单,看起来很稳固。并且不需要锁定;)
答案 2 :(得分:0)
如果您使用的是ClanLib游戏SDK,那么它是一个完善的,经过测试和支持的SDK。没有违法行为,但是,由于你是新手,这个问题在你的代码中比他们更有可能。
我发现很难相信这样一个完善的图书馆会发展出一个不足,即使它确实如此,我怀疑最好的解决方案是added my own thread, that keeps generating sound on the background
。我这样说是因为我怀疑你采取了错误的方法,如果你能找到一个ClanLib的解决方案,那么你将不需要你的线程&你的问题将会消失,而不需要解决。
你发布代码是goo,谢谢。我现在就去看看。
而且,最后,作为我的忠实粉丝,首先在官方ClanLib forum首先询问是不是更好?
编辑:是什么让你如此确定这是一个不足?我仍然觉得很难相信,但如果你在程序中检测到它,那么为什么不sleep()
,而不是产生声音? (多长时间睡觉?你怎么知道产生多少声音?并且产生的声音是否会干扰“真实”的声音?)
答案 3 :(得分:0)
实际上,我不知道问题是什么,它是偶然修复的......
我遇到了一个相关的问题,这个问题是由删除线程时的竞争条件引起的......我移动了一些代码(我甚至不需要重新编码),它也消失了。现在事情非常稳定! (好吧,仍然有不足,但现在更难得)