Создание примера, показывающего потоки, изменяющие общую переменную

Я хочу создать пример, показывающий сбой при использовании параллельных циклов. Я пытаюсь составить пример, который показывает в Prallel. Для двух потоков могут изменяться общие (нелокальные) переменные. Для этого я пишу следующий пример, в котором поток присваивает свой номер переменной, а затем мы добавляем задержку, чтобы увидеть, переопределит ли какой-либо другой поток эту переменную или нет. На выходе это переопределение никогда не происходит со мной.

            Parallel.For(0, result.Length, ii =>
            {
                int threadNum = Thread.CurrentThread.ManagedThreadId;
                Thread.Sleep(10000);
                if (threadNum != Thread.CurrentThread.ManagedThreadId)
                    Console.WriteLine("threadNum = {0}, Thread.CurrentThread.ManagedThreadId = {1}", threadNum, Thread.CurrentThread.ManagedThreadId);
            });

Можно возразить, что я задерживаю все темы. Поэтому я добавляю задержку только к одному потоку:

        int num = -1; 
        Parallel.For(0, result.Length, ii =>
        {
            if( num == -1)
                num = Thread.CurrentThread.ManagedThreadId;
            int threadNum = Thread.CurrentThread.ManagedThreadId;

            if (Thread.CurrentThread.ManagedThreadId == num) 
            {
                Console.WriteLine("num = {0}", num);
                Thread.Sleep(10);
            }
            if (threadNum != Thread.CurrentThread.ManagedThreadId)
                Console.WriteLine("threadNum = {0}, Thread.CurrentThread.ManagedThreadId = {1}", threadNum, Thread.CurrentThread.ManagedThreadId);

        });

Здесь он просто запоминает первый поток и только задерживает его. Тем не менее я не наблюдаю никакого переопределения переменной 'threadNum' потоками.

Любые идеи?


person Daniel    schedule 28.07.2014    source источник


Ответы (1)


Ваш threadNum объявлен в замыкании, поэтому каждый поток будет иметь свою собственную копию.

Вы можете переместить его за пределы закрытия.

Возможно, лучший способ продемонстрировать проблемы с параллелизмом — иметь несколько потоков, увеличивающих одну и ту же переменную (которая определена в области, доступной для всех потоков). Оператор ++ не является атомарным, поэтому конечный результат вряд ли будет равен NumberOfThreads * NumberOfIterationsPerThread (при условии, что вы начинаете с нуля).

person Eric J.    schedule 28.07.2014
comment
Ага, понятно! Итак, вы говорите, что, поскольку каждый поток начинает запускать всю область видимости, каждый раз он создает новую локальную переменную для каждого потока! Верно? - person Daniel; 29.07.2014