Локальная переменная внутри параллельных циклов потокобезопасность
У меня есть переменная (cnt
) внутри вложенный parallel.foreach
, Я запускаю эту программу и, видимо, она работает хорошо. Кто-нибудь знает, что этот код действительно потокобезопасен? Можно ли определить переменную внутри parallel
петли?
Спасибо.
object obj = new object();
int total=0;
Parallel.For(0, 2, i =>
{
Parallel.For(0, 1000000, j =>
{
int cnt = 0;
if ((arr[i, j] % 2) == 0)
{
Interlocked.Increment(ref cnt);
}
lock (obj)
{
total= total+ (cnt / 2);
}
});
});
2 ответа
Этот код является потокобезопасным - единственные общие данные (total
) правильно синхронизирован. Это потокобезопасно даже без использования Interlocked.Increment
(т.е. до вашего редактирования).
Однако это не эффективно.
Было бы гораздо лучше использовать перегрузку с локальным инициализатором и, наконец, делегатами.
int total=0;
Parallel.For(0, 2,
{
Parallel.For(0, 1000000,
local => 0,
(j, state, local) =>
{
if ((arr[i, j] % 2) == 0)
{
++local;
}
return local;
},
local => Interlocked.Increment(ref total, local)
);
});
Этот код действительно безопасен, потому что lock
Заявление выступает в качестве полной операции ограждения. Это гарантирует, что операция приращения является атомарной и не будет подвергаться гонкам из других потоков.