C# Многопоточность Передача по значению или ссылке?

Я видел фрагмент кода в Интернете, в котором говорится, что вызов такого потока вызывает недетерминированный вывод «0223557799» или что-то в этом роде. (Вы поняли)

for (int i = 0; i < 10; i++)
   new Thread (() => Console.Write (i)).Start();

Это причина, указанная для этого:

"Проблема в том, что переменная i ссылается на одно и то же место в памяти на протяжении всего цикла. Поэтому каждый поток вызывает Console.Write для переменной, значение которой может меняться в процессе выполнения!"

Но, условно говоря, когда аргумент передается по значению, каждый новый вызов Thread должен отправлять i свой инкрементный порядок, верно? Только если значения передаются по ссылке, вышеупомянутая причина остается в силе. Итак, в C# Multi-Threading значения передаются по ссылке?

Я новичок в С#, пожалуйста, поймите, если вопрос наивен.


person Learner    schedule 21.07.2013    source источник
comment
интервал темп = я; поместите его внутри цикла и передайте temp, slaks прав.   -  person terrybozzio    schedule 21.07.2013


Ответы (2)


Здесь есть более чем одна проблема. Это, безусловно, начинается с проблемы захвата переменной цикла for(), описанной в этом запись в блоге. Это имеет тенденцию выдавать «10» в качестве вывода, но нет никакой гарантии, что это произойдет, поскольку поток может выполняться, пока цикл все еще повторяется.

Но программа также страдает из-за основной проблемы с потоками, нет никакой гарантии, что потоки вызовут Console.Write() в ожидаемом порядке. Это просто вероятно, но один поток может опередить другой и получить блокировку, защищающую консоль. Проблема, известная как "гонка потоков".

person Hans Passant    schedule 21.07.2013
comment
Изменение в C# 5 применяется только к циклам foreach, а не к циклам for. - person Eric Lippert; 21.07.2013

Ваша программа эквивалентна следующей программе:

class Locals
{
    public int i;
    public void M() { Console.Write(this.i);
}

...
Locals locals = new Locals();
for (locals.i = 0; locals.i < 10; locals.i++)
  new Thread (locals.M).Start();

Теперь понятно, почему вы получаете такие результаты? По значению передается не i; скорее это locals, которое передается по ссылке в каждый поток. Каждый поток общий locals.i и поэтому может видеть текущее значение locals.i, а не значение, которое было i при создании потока.

person Eric Lippert    schedule 21.07.2013