다른 답변과 마찬가지로, sum
변수를 여러 스레드 (Parallel.ForEach의 기능)에서 업데이트하면 스레드로부터 안전한 동작이 아닙니다. 업데이트를 수행하기 전에 잠금을 획득하는 간단한 수정을 통해 은 문제를 해결할 수 있습니다.
double sum = 0.0;
Parallel.ForEach(myCollection, arg =>
{
lock (myCollection)
{
sum += ComplicatedFunction(arg);
}
});
그러나 이것은 또 다른 문제점을 야기합니다. 각 반복마다 잠금이 획득되므로 각 반복의 실행이 효과적으로 직렬화됨을 의미합니다. 다시 말해, 평범한 구형 인 foreach
루프를 사용하는 것이 더 낫습니다.
이제이 문제를 해결하려면 문제를 별도의 고정 척으로 나누는 것이 좋습니다. 다행히도 합계 연산은 연관성 있고 연관성이 있으며 반복의 중간 결과가 독립적이기 때문에 반복 작업의 결과를 합산하면 원하는 일을 할 때 매우 쉽게 할 수 있습니다.
이렇게하는 방법은 다음과 같습니다.
double sum = 0.0;
Parallel.ForEach(myCollection,
() => // Initializer
{
return 0D;
},
(item, state, subtotal) => // Loop body
{
return subtotal += ComplicatedFunction(item);
},
(subtotal) => // Accumulator
{
lock (myCollection)
{
sum += subtotal;
}
});
보기 [ 증가 parallel.foreach 범위 외부 카운트 값 (http://stackoverflow.com/questions/2394447/increment-a-count-value-outside-parallel-foreach-scope). 기본적으로 [Interlocked] (http://msdn.microsoft.com/en-us/library/55dzx06b.aspx)를 사용할 수 있지만 가능한 경우 부작용을 피하는 것이 좋습니다. –