Демонстрация этого пост-декремента не атомарна ... FAIL - PullRequest
0 голосов
/ 10 ноября 2011

Я пробовал пример кода из этой книги , который должен продемонстрировать, что оператор после декремента не является атомарным. Код такой, какой я его ввел в LinqPad.

void Main() {
  var count = 0;
  do {
    _x = 10000;
    for (int i = 0; i < 100; i++) {
      new Thread(Go).Start();
    }
    Thread.Sleep(1000);

    Console.WriteLine("Try "+ count);
    count++;
  } while (_x == 0);
  Console.WriteLine(_x);
}

int _x = 10000;
void Go() { for (int i = 0; i < 100; i++) _x--; }

Идея состоит в том, что уменьшение _x параллельно на нескольких потоках без блокировки может привести к значению _x, отличному от 0, когда все потоки закончили.

Моя проблема в том, что как бы долго я ни старался, в результате я всегда получаю 0. Я запустил код на двух разных компьютерах (оба на Windows 7) и в двух разных версиях .NET, и оба дали мне один и тот же результат.

Что мне здесь не хватает?

1 Ответ

1 голос
/ 10 ноября 2011

Я добавил 100000 взаимодействий в Go, как предложил Лассе В. Карлсен. Код теперь работает как положено с первой попытки. Я также переместил создание потоков из цикла и уменьшил количество потоков, как предложил Хенк Холтерман.

void Main()
{
    var count = 0;
    do {
    _x = 1000000;
    var threads = Enumerable.Range(0,10).Select (_ => new Thread(Go)).ToList();

    foreach (var t in threads)
    {
        t.Start();
    }

    Thread.Sleep(1000);
    Console.WriteLine("Try "+ count);
    count++;
    } while (_x == 0);
    Console.WriteLine(_x);
}

int _x;
void Go() { for (int i = 0; i < 100000; i++) _x--; }

Код теперь работает как положено.

...