This is a mirror of official site: http://jasper-net.blogspot.com/

Spin Lock in C++

| Tuesday, May 3, 2011
Introduction 

If we use common synchronization primitives like mutexes and critical sections then the following sequence of events occur between two threads that are looking to acquire a lock.

Thread 1 acquires lock L and executes
T2 tries to acquire lock L, but since its already held and therefore blocks incurring a context switch
T1 release the lock L. This signals T2 and at lower level this involves some sort of kernel transition.
T2 wakes up and acquires the lock L incurring another context switch.
So there are always at least two context switches when primitive synchronization objects are used. A spin lock can get away with expensive context switches and kernel transition.

Most modern hardware supports atomic instructions and one of them is called ‘compare and swap’ (CAS). On win32 systems they are called interlocked operations. Using these interlocked functions, an application can compare and store a value in an atomic uninterruptible operation. With interlocked functions, it is possible to achieve lock freedom to save expensive context switches and kernel transitions which can be bottleneck in a low latency application. On a multiprocessor machine a spin lock (a kind of busy waiting) can avoid both of the above issues to save thousands of CPU cycles in context switches. However, the downside of using spin locks is that they become wasteful if held for longer period of time in which case they can prevent other threads from acquiring the lock and progressing. The implementation shown in this article is an effort to develop a general purpose spin lock.

Algorithm

A typical (or basic) spin lock acquire and release functions would look something like below.

// acquire the lock
class Lock
{
    volatile int dest = 0;
    int exchange = 100;
    int compare = 0;
    void acquire()
    {
        While(true)
        {
            if(interlockedCompareExchange(&dest, exchange, compare) == 0)
            {
                // lock acquired 
                break;
            }
        }
    }
    // release the lock
    Void release()
    {
        // lock released 
       dest = 0; 

Read more: Codeproject

Posted via email from Jasper-net

0 comments: