Go to main content

Multithreaded Programming Guide

Exit Print View

Updated: March 2019
 
 

Using Spin Locks

Spin locks are a low-level synchronization mechanism suitable primarily for use on shared memory multiprocessors. When the calling thread requests a spin lock that is already held by another thread, the second thread spins in a loop to test if the lock has become available. When the lock is obtained, it should be held only for a short time, as the spinning wastes processor cycles. Callers should unlock spin locks before calling sleep operations to enable other threads to obtain the lock.

Spin locks can be implemented using mutexes and conditional variables, but the pthread_spin_* functions are a standardized way to practice spin locking. The pthread_spin_* functions require much lower overhead for locks of short duration.

When performing any lock, a trade-off is made between the processor resources consumed while setting up to block the thread and the processor resources consumed by the thread while it is blocked. Spin locks require few resources to set up the blocking of a thread and then do a simple loop, repeating the atomic locking operation until the lock is available. The thread continues to consume processor resources while it is waiting.

Compared to spin locks, mutexes consume a larger amount of processor resources to block the thread. When a mutex lock is not available, the thread changes its scheduling state and adds itself to the queue of waiting threads. When the lock becomes available, these steps must be reversed before the thread obtains the lock. While the thread is blocked, it consumes no processor resources.

Therefore, spin locks and mutexes can be useful for different purposes. Spin locks might have lower overall overhead for very short-term blocking, and mutexes might have lower overall overhead when a thread will be blocked for longer periods of time.

Initializing a Spin Lock

Use the pthread_spin_init(3C) function to allocate resources required to use a spin lock, and initialize the lock to an unlocked state.

pthread_spin_init() Syntax

int  pthread_spin_init(pthread_spinlock_t *lock, int pshared);
#include <pthread.h>

pthread_spinlock_t lock;
int pshared;
int ret;

/* initialize a spin lock */
ret = pthread_spin_init(&lock, pshared); 

The pshared attribute has one of the following values:

PTHREAD_PROCESS_SHARED

Description: Permits a spin lock to be operated on by any thread that has access to the memory where the spin lock is allocated. Operation on the lock is permitted even if the lock is allocated in memory that is shared by multiple processes.

PTHREAD_PROCESS_PRIVATE

Description: Permits a spin lock to be operated upon only by threads created within the same process as the thread that initialized the spin lock. If threads of differing processes attempt to operate on such a spin lock, the behavior is undefined. The default value of the process-shared attribute is PTHREAD_PROCESS_PRIVATE.

pthread_spin_init() Return Values

Upon successful completion, the pthread_spin_init() function returns 0. Otherwise, one of the following error codes is returned.

EAGAIN

Description: The system lacks the necessary resources to initialize another spin lock.

EBUSY

Description: The system has detected an attempt to initialize or destroy a spin lock while the lock is in use (for example, while being used in a pthread_spin_lock() call) by another thread.

EINVAL

Description: The value specified by lock is invalid.

Acquiring a Spin Lock

Use the pthread_spin_lock(3C) to lock a spin lock. The calling thread acquires the lock if it is not held by another thread. Otherwise, the thread does not return from the pthread_spin_lock() call until the lock becomes available. The results are undefined if the calling thread holds the lock at the time the call is made.

pthread_spin_lock() Syntax

int  pthread_spin_lock(pthread_spinlock_t *lock);
#include <pthread.h>

pthread_spinlock_t lock;
int ret;

ret = pthread_ spin_lock(&lock); /* lock the spinlock */

pthread_spin_lock() Return Values

Upon successful completion, the pthread_spin_lock() function returns 0. Otherwise, one of the following error codes is returned.

EDEADLK

Description: The current thread already owns the spin lock.

EINVAL

Description: The value specified by lock does not refer to an initialized spin lock object.

Acquiring a Non-Blocking Spin Lock

Use the pthread_spin_trylock(3C) function to lock a spin lock and fail immediately if the lock is held by another thread.

pthread_spin_trylock() Syntax

int  pthread_spin_trylock(pthread_spinlock_t *lock);
#include <pthread.h>

pthread_spinlock_t lock;
int ret;

ret = pthread_spin_trylock(&lock); /* try to lock the spin lock */

pthread_spin_trylock() Return Values

Upon successful completion, the pthread_spin_trylock() function returns 0. Otherwise, one of the following error codes is returned.

EBUSY

Description: A thread currently owns the spin lock.

EINVAL

Description: The value specified by lock does not refer to an initialized spin lock object.

Unlocking a Spin Lock

Use the pthread_spin_unlock(3C) function to release a locked spin lock.

pthread_spin_unlock() Syntax

int  pthread_spin_unlock(pthread_spinlock_t *lock);
#include <pthread.h>

pthread_spinlock_t lock;
int ret;

ret = pthread_spin_unlock(&lock); /* spinlock is unlocked */

pthread_spin_unlock() Return Values

Upon successful completion, the pthread_spin_unlock() function returns 0. Otherwise, one of the following error codes is returned.

EPERM

Description: The calling thread does not hold the lock.

EINVAL

Description: The value specified by lock does not refer to an initialized spin lock object.

Destroying a Spin Lock

Use the pthread_spin_destroy(3C) function to destroy a spin lock and release any resources used by the lock.

pthread_spin_destroy() Syntax

int  pthread_spin_destroy(pthread_spinlock_t *lock);
#include <pthread.h>

pthread_spinlock_t lock;
int ret;

ret = pthread_spin_destroy(&lock); /* spinlock is destroyed */

The effect of subsequent use of the lock is undefined until the lock is reinitialized by another call to pthread_spin_init(). The results are undefined if pthread_spin_destroy() is called when a thread holds the lock, or if this function is called with an uninitialized thread spin lock.

pthread_spin_destroy() Return Values

EBUSY

Description: The system has detected an attempt to initialize or destroy a spin lock while the lock is in use (for example, while being used in a pthread_spin_lock() call) by another thread.

EINVAL

Description: The value specified by lock is invalid.