Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parallel.For not handling lock properly

I've done the following test:

private static object threadLocker = new object();

private static long threadStaticVar;
public static long ThreadStaticVar
{
    get
    {
        lock (threadLocker)
        {
            return threadStaticVar;
        }
    }
    set
    {
        lock (threadLocker)
        {
            threadStaticVar = value;
        }
    }
}

Parallel.For(0, 20000, (x) =>
{
    //lock (threadLocker) // works with this lock
    //{
        ThreadStaticVar++;
    //}
});

This Parallel.For invokes the method passing the values from 0 to 19999. So it would execute 20k times.

If I don't wrap ThreadStaticVar++; with a lock, even though it has a lock on its get and set, the result will not be 20000. If I remove the comment bars and lock it inside the .For it gets the right value.

My question is: How does it work? Why the lock on the get and set doesn't work? Why it works only inside my For?

like image 899
BrunoLM Avatar asked Sep 18 '25 23:09

BrunoLM


1 Answers

The ++ operator isn't an atomic increment. There will be a call to get followed by a call to set, and those calls can be interleaved among different threads since the lock is only on each individual operation. Think of it like this:

lock {tmp = var}
lock {var = tmp+1}

Those locks don't look so effective now, do they?

like image 162
tzaman Avatar answered Sep 20 '25 15:09

tzaman