3

好的,据您所知,我将解释这个问题:我正在使用一个名为 ClanLIB 的库(不是我的选择),该库 SEEMLY(我不确定,甚至阅读源代码)创建了一个处理声音的线程。

该线程在缓冲区为空时尝试获取更多数据,通常这会导致数据生成库太慢而无法在声卡到达缓冲区结束之前提供更多数据时导致欠载。

所以我添加了我自己的线程,它不断在背景上产生声音。

这工作得很好,除了我自己的线程有时会劫持过多的 CPU 时间并冻结其他所有内容。为了解决这个问题,我添加了条件等待。

当缓冲区已满时发生条件等待,当 ClanLIB 请求更多数据时,会发出等待信号,因此缓冲区写入线程会恢复(直到再次满)。

我的问题是,由于我添加了这个条件等待、ClanLIB 声音线程和我自己的音乐线程,有时会“失控”,在应用程序的其余部分冻结时播放音乐。

什么样的奇怪情况会导致这种情况?

伪代码:

//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()
}
4

4 回答 4

1

您在互斥锁区域内做的太多了 - 您很可能在 cond1 信号上陷入僵局。你应该尽可能少地在锁定区域内做,因为你做的越多,你引入死锁的风险就越大 - 你绝对不应该等待保护信号发送的互斥锁内的信号 - 如果你'重新等待,它永远不会被发送 - condition_wait 没有解锁你的互斥对象,它怎么知道呢?

“通过添加条件等待解决”是一个强有力的指标,你有一个导致死锁的竞争条件 - 你还没有解决问题,只要你的逻辑的执行时间因任何原因发生变化,比如因为另一个应用程序正在运行,死锁可以返回。

于 2010-08-13T20:21:48.917 回答
1

我也将 clanlib 用于项目,但将 OpenAL 用于声音。它似乎与提供缓冲区等的工作方式相同。

我还使用单独的线程来处理声音,但我的解决方案是在每次尝试输入缓冲区后添加一个固定的睡眠时间。它很简单,看起来很可靠。并且不需要锁定;)

于 2010-09-21T10:44:34.197 回答
0

如果您使用的是 ClanLib 游戏 SDK,它是一个经过完善、测试和支持的 SDK。无意冒犯,但是,由于您是公认的新手,因此您的代码中的问题比他们的问题更可能出现。

我很难相信这样一个完善的图书馆会发展成一个不足,即使它确实如此,我怀疑最好的解决方案是added my own thread, that keeps generating sound on the background. 我这样说是因为我怀疑您采用了错误的方法,并且如果您可以使用 ClanLib 找到解决方案,那么您将不需要您的线程并且您的问题将消失而无需解决。

很高兴您发布代码,谢谢。我现在就去看看。

最后,作为 SO 的忠实粉丝,首先在官方ClanLib 论坛上提问不是更好吗?


编辑:是什么让你如此确定它是一个underrun?我仍然觉得这很难相信,但如果你在你的程序中检测到它,那为什么不sleep()呢,而不是产生声音呢?(睡多久?你怎么知道要产生多少声音?产生的声音不会干扰“真实”的声音吗?)

于 2010-08-11T23:53:01.057 回答
0

其实不知道是什么问题,一不小心就解决了。。。

我有一个相关的问题,这个问题是由删除线程时的竞争条件引起的......我移动了一些代码(我什至不需要重新编码任何东西)并且它也消失了。现在事情完全稳定了!(嗯,仍然有欠载,但现在更罕见了)

于 2010-08-30T02:37:50.567 回答