Параллельное программирование с блокировкой C # - PullRequest
3 голосов
/ 13 ноября 2011

Я запутался с примером на

http://msdn.microsoft.com/en-us/library/dd997393.aspx

Parallel.ForEach<int, long>(nums, // source collection
                                    () => 0, // method to initialize the local variable
                                    (j, loop, subtotal) => 
                                    {
                                        subtotal += nums[j]; 
                                        return subtotal; 
                                    },

                                    (finalResult) => Interlocked.Add(ref total,finalResult)                                        );

Не знаю, почему последний делегат (finalResult) => Interlocked.Add(ref total,finalResult) требуется блокировка, тогда как предыдущее выражение

(j, loop, subtotal) => 
                                    {
                                        subtotal += nums[j]; 
                                        return subtotal; 
                                    },

нет?

Спасибо

Ответы [ 2 ]

3 голосов
/ 13 ноября 2011

Методы Parallel.For() и Parallel.ForEach() используют Partitioner. Было бы очень неэффективно выполнять цикл из 10 000 элементов на 10 000 отдельных задач. Разделитель разбивает данные на сегменты, и в идеале ForEach() будет выполняться в 4 Задачи (потоки) из 2500 элементов на 4-ядерном процессоре. Иногда это требует некоторой эвристики, и вы можете написать свой собственный разделитель.

При использовании «обычных» (простых) перегрузок ForEach() это полностью прозрачно. Но в вашем примере используется одна из перегрузок <TLocal>, которая покрывает разделение.

Оператор subtotal += nums[j]; повторяется внутри 1 раздела и поэтому является потокобезопасным.

И (finalResult) => Interlocked.Add(ref total,finalResult), где разделы объединяются, эта часть, конечно, не является поточно-ориентированной.

2 голосов
/ 13 ноября 2011

Переменная subtotal - это «локальные данные», к которым имеет доступ только один поток.

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

...