Безопасно ли использовать Bools для синхронизации нескольких потоков?

StackOverflow https://stackoverflow.com/questions/4180640

  •  10-10-2019
  •  | 
  •  

Вопрос

Я пишу аудио -приложение с несколькими потоками, производящими звук, и один поток, который смешивает звуки и отправляет их на звуковую карту. Я пробовал несколько способов синхронизации потоков «правильный» способ, включая сигналы и безопасные очереди потока, но они были слишком медленными. Итак, теперь я использую Bool для каждого производителя, чтобы указать, заполнена ли его очередь. Похоже, он работает очень хорошо (задержка 5 мс для 32 потоков), но безопасно ли это сделать?

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;
        }
Это было полезно?

Решение

Нет, это не совсем безопасно, но большую часть времени вам повезло ;-) Вы должны использовать Блокируется Методы для доступа к Bool.

Другие советы

Насколько я знаю, модель памяти .NET не гарантирует, что изменения переменной, сделанной в одном потоке, будут видны в другом потоке. Вам нужна память барьер там. Самый простой (хотя и не самый эффективный) способ организации, используя использование lock или же Interlocked методы

Кстати, занятое ожидание - не лучший способ для достижения вашей цели. Может быть, вы хотите перейти на Производитель-потребитель модель с соответствующей переменной условием (MonitorS в C# PALLANCE) Использование?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top