简体   繁体   中英

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

Consider this piece of code that creates a closure around counter :

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

(Please set aside for a moment the obvious problem of using a counter within a parallel foreach).

Will tmp ever evaluate to 0x0000 or 0x1FFFF?

My reasoning: To increment counter from 0xFFFF to 0x10000 requires at least a two-byte CPU instruction that could be interrupted by multithreading. If it gets interrupted, there is a chance that only one byte of counter will be updated -- it could temporarily be set to 0x00000 or 0x1FFFF.

Should I have written this as:

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

...?

And if I get rid of AsParallel , am I completely safe?

Yes, you need Interlocked.Increment , closure doesn't change the fact that this operation isn't thread safe. What closure will do is lift you lambda expression into a display class and re-use that same class each iteration which will cause multiple threads incrementing the counter.

Decompiling looks like this:

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));
    }
}

And if I get rid of AsParallel , am I completely safe?

As long as the list or counter aren't mutated while you're iterating, you should be ok. From you example it isn't possible to know the actual locality of the data you're working with, but assuming everything is method scope local, you'll be fine.

Yup. Parallel is just syntactic sugar for multi-threading. You still need to be thread-safe. If you are single threaded, you obviously don't need Interlocked (or to be thread safe).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM