簡體   English   中英

當有封閉時我是否需要使用互鎖?

[英]Do I need to use interlocked when there is a closure?

考慮這段代碼在counter周圍創建一個閉包:

uint counter = 0xFFFF;
someList.AsParallel().ForEach(a => { uint tmp = ++counter });

(請暫時擱置在並行foreach中使用計數器的明顯問題)。

tmp會評估為0x0000還是0x1FFFF?

我的理由:要將counter從0xFFFF遞增到0x10000,至少需要一個可被多線程中斷的雙字節CPU指令。 如果它被中斷,則有可能只更新一個字節的counter - 它可以暫時設置為0x00000或0x1FFFF。

我應該把它寫成:

uint counter = 0xFFFF;
someList.AsParallel().ForEach(a => { uint tmp = Interlocked.Increment(counter) });

...?

如果我擺脫AsParallel ,我完全安全嗎?

是的,你需要Interlocked.Increment ,閉包不會改變這個操作不是線程安全的事實。 什么閉包將把你的lambda表達式提升到一個顯示類中,並在每次迭代時重復使用相同的類,這將導致多個線程遞增計數器。

反編譯看起來像這樣:

public class C
{
    [CompilerGenerated]
    private sealed class <>c__DisplayClass0_0
    {
        public uint counter;
        internal void <M>b__0(int a)
        {
            uint num = this.counter + 1u;
            this.counter = num;
        }
    }
    public void M()
    {
        C.<>c__DisplayClass0_0 <>c__DisplayClass0_ = new C.<>c__DisplayClass0_0();
        <>c__DisplayClass0_.counter = 65535u;
        List<int> source = new List<int> {
            1,
            2,
            3
        };
        source.AsParallel<int>().ForAll(new Action<int>(<>c__DisplayClass0_.<M>b__0));
    }
}

如果我擺脫AsParallel ,我完全安全嗎?

只要在迭代時列表或計數器沒有變異,你應該沒問題。 從您的示例中,您無法知道您正在使用的數據的實際位置,但假設一切都是方法范圍本地,您會沒事的。

對。 Parallel是多線程的語法糖。 你仍然需要線程安全。 如果你是單線程,你顯然不需要Interlocked(或線程安全)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM