Atomic Blocking

Yes, I know that the next question can be answered using "Use the lock keyword" or something similar. But since it’s just “fun,” I don’t care.

I made a simple lock using atomic operations:

public class LowLock 
{
    volatile int locked = 0;

    public void Enter(Action action)
    {
        var s = new SpinWait();

        while (true)
        {
            var inLock = locked; // release-fence (read)

            // If CompareExchange equals 1, we won the race.
            if (Interlocked.CompareExchange(ref locked, 1, inLock) == 1)
            {
                action();
                locked = 0; // acquire fence (write)
                break; // exit the while loop
            }
            else s.SpinOnce(); // lost the race. Spin and try again.
        } 
    }
}

I use the lock above in a simple for loop that adds a line to the normal List<string>one to make the method addthread safe when it is wrapped inside a method Enterfrom a LowLock.

The code looks like this:

static void Main(string[] args)
{
    var numbers = new List<int>();

    var sw = Stopwatch.StartNew();
    var cd = new CountdownEvent(10000);

    for (int i = 0; i < 10000; i++)
    {
        ThreadPool.QueueUserWorkItem(o =>
        {
            low.Enter(() => numbers.Add(i));
            cd.Signal();
        });
    }

    cd.Wait();
    sw.Stop();

    Console.WriteLine("Time = {0} | results = {1}", sw.ElapsedMilliseconds, numbers.Count);

    Console.ReadKey();
}

, , Console.WriteLine, , , CountdownEvent (10000) - It , 9983 , - 9993. ?

+5
2

SpinLock, , , , .


, , .

, 0 "unlocked" 1 "".

:

if (Interlocked.CompareExchange(ref locked, 1, inLock) == 1)

. locked 1 (), , inLock = locked (, , ). , , 1 (), , .

, ( value == 0) , ( value == 1), 0 () comparand, :

if (Interlocked.CompareExchange(ref locked, 1, 0) == 0)

, , , List<T>.Add "" , . , Interlocked.CompareExchange , , ( , -).

, (, , ) , . , , .

EDIT: 0.

+6

Interlocked.CompareExchange , - :

public class LowLock
{
    int locked = 0;

    public void Enter( Action action )
    {
        var s = new SpinWait();

        while ( true )
        {
            // If CompareExchange equals 0, we won the race.
            if ( Interlocked.CompareExchange( ref locked, 1, 0 ) == 0 )
            {
                action();
                Interlocked.Exchange( ref locked, 0 );
                break; // exit the while loop
            }

            s.SpinOnce(); // lost the race. Spin and try again.
        }
    }
}

volatile reset , volatile is hard

+2

All Articles