Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用bools同步多个线程安全吗?_C#_Multithreading_Synthesizer - Fatal编程技术网

C# 使用bools同步多个线程安全吗?

C# 使用bools同步多个线程安全吗?,c#,multithreading,synthesizer,C#,Multithreading,Synthesizer,我正在编写一个音频应用程序,它有多个线程产生声音,一个线程混合声音并将其发送到声卡。我尝试了几种以“正确”的方式同步线程的方法,包括信号和线程安全队列,但它们都太慢了。所以现在我为每个生产者使用bool来指示其队列是否已满。它似乎工作得很好(32个线程的延迟为5毫秒),但这样做安全吗 class PlayThreadParameters { public Queue<Samples> queue; public bool isOutputQueueFull; } 消

我正在编写一个音频应用程序,它有多个线程产生声音,一个线程混合声音并将其发送到声卡。我尝试了几种以“正确”的方式同步线程的方法,包括信号和线程安全队列,但它们都太慢了。所以现在我为每个生产者使用bool来指示其队列是否已满。它似乎工作得很好(32个线程的延迟为5毫秒),但这样做安全吗

class PlayThreadParameters
{
    public Queue<Samples> queue;
    public bool isOutputQueueFull;
}
消费者如下所示(由Naudio从单独的线程调用):

公共重写整型读取(字节[]数组、整型偏移量、整型计数)
{
对于(int v=0;v
不,它不是完全安全的,但大多数时候你可能会很幸运;-)您应该使用这些方法来访问bool。

据我所知,.NET内存模型不能保证在一个线程中所做的变量更改在另一个线程中可见。你需要一个记忆。最简单(但不是最有效)的组织方式是使用
锁定
联锁
方法


顺便说一句,忙碌的等待并不是实现目标的最佳方法。也许您想切换到具有适当条件变量的(
Monitor
s在C#术语中)用法?

您如何设置isplay变量?@marcind isplay在用户按下停止按钮+1时设置为false,我还打算建议联锁方法。变量还应标记为
volatile
。不幸的是,.net 3.5中没有联锁。但是设置布尔原子不是吗?@Erwin J.:
volatile
仍然不能保证多核的原子性-每个核都有自己的缓存,除非通过互锁指令,否则不会刷新缓存。互锁也适用于3.5。读取/写入32位或更小的值是原子性的,但您需要联锁(可能是易失性的)的原因是因为指令执行顺序不正确,JIT、OS和处理器本身都可以按照各种规则无序执行指令。如果CPU 1上的线程1正在写入您的bool,那么稍后CPU 2上的线程2正在读取,则线程2可能会看到您的bool有一个过时的值,除非您使用联锁。@Erwin J。感谢您提供到其他问题的链接。下面是另一篇关于虚假分享这个令人兴奋的话题的文章,以防你遇到这个问题。
  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;
    }
}
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;
        }