Search code examples
c#multithreadinglock-free

Is locking required when only one thread accesses a value at a time?


My idea is to run a few operations asynchronously; I can guarantee that two operations will never run concurrently, but I can't guarantee that they will run on the same thread/CPU as the others.

// Example code
int myValue = 0;

ThreadPool.QueueUserWorkItem(state => {
    myValue++;

    ThreadPool.QueueUserWorkItem(state2 => {
        Console.WriteLine(myValue);
    });
});

Is the output guaranteed to be 1 even without locking?

Maybe a call to Thread.MemoryBarrier() is required before the Console.WriteLine(myValue)?

Or maybe myValue should be made volatile?

I'm not really used to multithreading programming without locking, I hope someone can solve my doubts.

Thanks!

EDIT:

What if I decide to use locking? Is this code guaranteed to output 1?

If yes, why? Could not the compiler decide to store myValue on the register of a CPU?

I have never actually had any problem with a code like this, but I've only run my programs on x86 and x64 CPUs so far. What about MONO, ARM, and other "esoteric" platforms?

// Example code
object lockMe = new object();
int myValue = 0;

ThreadPool.QueueUserWorkItem(state => {
    lock(lockMe) {
        myValue++;
    }

    ThreadPool.QueueUserWorkItem(state2 => {
        lock(lockMe) {
            Console.WriteLine(myValue);
        }
    });
});

Thanks again!


Solution

  • ThreadPool.QueueUserWorkItem, like any other library functions which executes code in the other thread, garantees that this code will see every modification, visible by the current thread up to the function call.

    Because myValue++ precedes ThreadPool.QueueUserWorkItem() in program order, result of value's modification is seen by the caller thread. So Console.WriteLine(myValue) will definitely see updated value.

    Locking, volatile modifier are completely unnecessary in that case.