Многопоточность - понимание барьеров памяти и нестабильности - PullRequest
0 голосов
/ 18 февраля 2019

Я изучаю потоки в c #, следуя знаменитым «C # в двух словах», и во время исследования феноменов Thread.MemoryBarrier () я был напуган до смерти, когда наткнулся на пример Брайана на Почему нам нужен Thread.MemoryBarrier ()? .

У меня процессор i-7 8700K и 4.6.1 .NET, и мне удалось воспроизвести проблему (программа никогда не заканчивается) даже при следующих изменениях в программе:

class Program
{
    static bool stop = false;

    public static void Main(string[] args)
    {
        var t = new Thread(() =>
        {
            Console.WriteLine($"Thread begin");
            bool toggle = false;
            //while (true)
            while (!stop) 
            {
                if (stop)
                {
                    break;
                }
                toggle = !toggle;
            }
            Console.WriteLine($"Thread end");
        });
        t.Start();
        Thread.Sleep(1000);
        stop = true;
        Console.WriteLine($"Stop flag set. Waiting for thread to end...");
        t.Join();
        Console.ReadKey();
    }
}

Итак, даже с проверкой «if (stop)» проблема воспроизводится, и я понимаю, почему.Когда я помещаю «Thread.MemoryBarrier ()» перед этой проверкой, проблема не воспроизводится (по крайней мере, мне не удалось воспроизвести ее), и я понимаю, почему.Но чего я не понимаю, так это того, почему проблема больше не воспроизводится, когда я изменяю условие while и ставлю «while (true)» вместо «while (! Stop)»?Это как-то связано со специальной обработкой выражения while (true)?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

почему проблема больше не воспроизводится, когда я изменяю условие while и ставлю «while (true)» вместо «while (! Stop)»?

Поведение зависит от нескольких факторовнапример: аппаратное обеспечение, операционная система, среда выполнения ... Например, на моей машине проблема не воспроизводится даже с вашим исходным кодом с while (!stop).И я считаю, что проблема может быть воспроизведена с while (true) в другой среде.

Эрик Липперт и Джон Скит заявляют, что нам не нужно использовать такие низкоуровневые методы, как Thread.MemoryBarrier, если только мы не являемся настоящими экспертами в этой области ( ссылка # 1 и ссылка # 2 ).Возможно, вам стоит подумать об использовании ключевого слова volatile с объявлением stop, которое выражает ваше намерение более четко и позволяет вам не использовать Thread.MemoryBarrierИли даже подумайте об использовании Task с CancellationToken, чтобы иметь возможность отменить Task.

Если посмотреть на ваше имя пользователя, то стоит отметить, что Эрик Липперт и Джон Скит в отношении .net похожи на Гэндальфа в отношениимагия

Обновление

Прочитайте комментарии Эрика Липперта ниже.Не используйте volatile, а также Thread.MemoryBarrier, пока действительно не понадобится.

0 голосов
/ 19 февраля 2019

В while (true).

нет ничего особенного. Ваш подробный ответ описан здесь: https://msdn.microsoft.com/en-us/magazine/jj863136.aspx

...