使用 bool 来同步多个线程是否安全?
我正在编写一个音频应用程序,该应用程序具有多个产生声音的线程和一个混合声音并将它们发送到声卡的线程。我尝试了几种以“正确”方式同步线程的方法,包括信号和线程安全队列,但它们都太慢了。所以现在我为每个生产者使用一个布尔值来指示其队列是否已满。它似乎工作得很好(32 个线程的延迟为 5 毫秒),但是这样做安全吗?
class PlayThreadParameters
{
public Queue<Samples> queue;
public bool isOutputQueueFull;
}
生产者看起来像这样:
public void PolyPlayThread(object o)
{
var playThreadParameters = (PlayThreadParameters)o;
while (isPlaying)
{
while (playThreadParameters.isOutputQueueFull)
{
if (!isPlaying)
return;
Thread.Sleep(1);
}
... //fill output queue
playThreadParameters.isOutputQueueFull = true;
}
}
消费者看起来像这样(由 Naudio 从单独的线程调用):
public override int Read(byte[] array, int offset, int count)
{
for (int v = 0; v < playThreadParameters.Length; v++)
while (!playThreadParameters[v].isOutputQueueFull)
{
if (!isPlaying)
return 0;
Thread.Sleep(1);
}
... //mix the samples from the outputqueues
for (int v = 0; v < playThreadParameters.Length; v++)
playThreadParameters[v].isOutputQueueFull =false;
return count;
}
I'm writing an audio application that has multiple threads producing sound and one thread that mixes the sounds and sends them to the sound card. I've tried several ways of synchronizing threads the 'right' way including Signals and thread safe queues but they were all too slow. So now I use a bool for each producer to indicate whether its queue is full. It seems to work very well (5ms latency for 32 threads) but is it safe to do it this way?
class PlayThreadParameters
{
public Queue<Samples> queue;
public bool isOutputQueueFull;
}
The producers look like this:
public void PolyPlayThread(object o)
{
var playThreadParameters = (PlayThreadParameters)o;
while (isPlaying)
{
while (playThreadParameters.isOutputQueueFull)
{
if (!isPlaying)
return;
Thread.Sleep(1);
}
... //fill output queue
playThreadParameters.isOutputQueueFull = true;
}
}
The consumer looks like this (called from a separate thread by Naudio):
public override int Read(byte[] array, int offset, int count)
{
for (int v = 0; v < playThreadParameters.Length; v++)
while (!playThreadParameters[v].isOutputQueueFull)
{
if (!isPlaying)
return 0;
Thread.Sleep(1);
}
... //mix the samples from the outputqueues
for (int v = 0; v < playThreadParameters.Length; v++)
playThreadParameters[v].isOutputQueueFull =false;
return count;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
据我所知,.NET 内存模型并不能保证一个线程中对变量所做的更改在另一个线程中可见。你需要一个内存屏障。最简单(尽管不是最有效)的组织方法是使用
lock
或Interlocked
方法。顺便说一句,忙碌的等待并不是实现目标的最佳方法。也许您想切换到具有适当条件变量(
Monitor
(用 C# 的说法)用法?As far as I know, the .NET memory model doesn't guarantee that the changes of a variable made in one thread will be visible in another thread. You need a memory barrier there. The simplest (though not the most efficient) way to organize that is by using
lock
orInterlocked
methods.By the way, busy waiting is not the best method to achieve your goal. Maybe you'd like to switch to the producer-consumer model with appropriate condition variable (
Monitor
s in C# parlance) usage?不,它并不完全安全,但大多数时候您可能会很幸运;-)您应该使用 访问 bool 的互锁方法。
No it is not completely safe, but you might get lucky most of the time ;-) You should be using the Interlocked methods to access the bool.