Подтвердить что ты не робот

Бесконечная петля в режиме деблокирования

Когда я запускаю следующий код в режиме отладки, он будет успешно завершен и завершен. Однако, если я запустил следующий код в режиме выпуска, он застрянет в бесконечном цикле и никогда не закончится.

static void Main(string[] args)
{
    bool stop = false;

    new Thread(() =>
    {
        Thread.Sleep(1000);
        stop = true;
        Console.WriteLine("Set \"stop\" to true.");

    }).Start();

    Console.WriteLine("Entering loop.");

    while (!stop)
    {
    }

    Console.WriteLine("Done.");
}

Какая оптимизация заставляет его застревать в бесконечном цикле?

4b9b3361

Ответ 1

Мое предположение было бы кешированием процессора переменной stop в основном потоке. В режиме отладки модель памяти более строгая, потому что отладчик должен иметь возможность обеспечить разумное представление состояния переменной во всех потоках.

Попробуйте создать поле и отметьте его как volatile:

volatile bool stop = false;

static void Main(string[] args)
{

    new Thread(() =>
    {
        Thread.Sleep(1000);
        stop = true;
        Console.WriteLine("Set \"stop\" to true.");

    }).Start();

    Console.WriteLine("Entering loop.");

    while (!stop)
    {
    }

    Console.WriteLine("Done.");
}

Ответ 2

Поскольку он не является потокобезопасным, вы обновляете переменную основного потока stop внутри дочернего потока. Это всегда будет непредсказуемо. Чтобы работать с любой ситуацией, как это, посмотрите эту статью.

Ключевое слово volatile инструктирует компилятор генерировать приобретать ограждение при каждом чтении с этого поля, а также каждая запись в это поле. Забор-ограждение предотвращает другие считывает/записывает из перемещения перед забором; забор предотвращает перемещение других прочтений/записей после забора. Эти "полузащитники" быстрее, чем полные заборы, потому что они дают время выполнения и аппаратное обеспечение больше возможностей для оптимизации.

Ответ 3

Тема Небезопасный код непредсказуем. Основная проблема заключается в изменении одной переменной потока из другого потока. Сделайте переменную глобальной или изменчивой. Вы можете сделать это, следуя

static volatile bool stop = false;

static void Main(string[] args)
{    
    new Thread(() =>
    {
        Thread.Sleep(1000);
        stop = true;
        Console.WriteLine("Set \"stop\" to true.");

    }).Start();

    Console.WriteLine("Entering loop.");

    while (!stop)
    {
    }

    Console.WriteLine("Done.");
}

Ответ 4

Похоже, что какая-то оптимизация для значения локальной переменной - изменение поля приводит к завершению ok (обратите внимание, что в реальном коде следует использовать летучую или правильную блокировку):

using System;
using System.Threading;

class Program
{
    static bool stop = false;
    static void Main(string[] args)
    {

        new Thread(() =>
        {
            Thread.Sleep(1000);
            stop = true;
            Console.WriteLine("Set \"stop\" to true.");

        }).Start();

        Console.WriteLine("Entering loop.");

        while (!stop)
        {
        }

        Console.WriteLine("Done.");
    }
}