У меня есть класс, подобный приведенному ниже:
class Program
{
static void Main(string[] args)
{
var outputWindow = new OutputWindow();
var threads = new List<Thread>();
Action action = () => outputWindow.Display(20);
for (int i = 0; i < 10; i++)
{
var thread = new Thread(() => action()) {Name = "Thread " + i};
threads.Add(thread);
}
foreach (var thread in threads)
{
thread.Start();
}
}
}
public class OutputWindow
{
public void Display(int x)
{
for (int i = 0; i < x; i++)
{
Console.WriteLine(Thread.CurrentThread.Name + " Outputcounter: " + i);
}
}
}
Вопрос в том, является ли этот поток безопасным и приведет ли это к каким-либо условиям гонки для локальной переменной i внутри метода отображения? Будут ли все потоки увеличивать значение переменной «i», как и ожидалось (то есть оно увеличивает значение и не вводит в другие потоки значение i)
Если это потокобезопасно, будет ли безопасно предположить, что любые локальные переменные, объявленные в методе, всегда являются потокобезопасными, а общие переменные — это те, которые нуждаются в синхронизации?
Спасибо, -Майк
action
(которая фиксирует в лямбде другую локальную переменную). Затем вы запускаете несколько потоков, давая каждому потоку новую лямбду, которая захватывает одну и ту же локальную переменнуюaction
. Эта переменнаяaction
действительно преобразуется в поле. Конечно, он не такой уж и локальный. Таким образом, эти локальные переменные не являются потокобезопасными. Когда вы спрашиваете о переменнойi
в своем коде, она действительно локальна. Он объявлен внутри метода, он не захватывается никакими лямбда-выражениями, не передается сref
илиout
, это неизменяемый тип. Так что проблем явно нет. - person Jeppe Stig Nielsen   schedule 17.01.2014i
в методеDisplay
.i
в методеMain
записывается в лямбда-выражении. И это явно проблематично.i
превращается в поле, которое встречается только в одном экземпляре. Вы, наверное, хотите это:for (int i = 0; i < 10; i++) { int copyOfI = i; var thread = new Thread(() => action()) {Name = "Thread " + copyOfI}; threads.Add(thread); }
. Это было отмечено и в ответе Хенка. При этомcopyOfI
будет преобразовано в поле экземпляра сгенерированного класса, и будет десять экземпляров этого класса. - person Jeppe Stig Nielsen   schedule 17.01.2014new Thread(() => action()) /* ANONYMOUS LAMBDA HAS STOPPED HERE */ {Name = "Thread " + i /* Not capturing */ };
. - person Jeppe Stig Nielsen   schedule 17.01.2014