Spinlock & Mutex

The Need for Synchronization

In a multiprocess and multithreaded environment, multiple tasks execute simultaneously and handle shared data. The reason why synchronization techniques are necessary in this process is to prevent the following phenomena.

  • ** Race Condition: ** When two or more processes or threads access a shared resource simultaneously, the result may unintentionally vary depending on the execution order.
  • Critical Section: This is a code area where multiple processes or threads access shared resources, and is a section where race conditions can occur.

In order to solve this Critical Section problem and ensure data consistency, a ** Mutual Exclusion mechanism is needed to prevent other processes from entering when one process enters the critical section. Representative examples include spinlocks and mutexes.

Spinlock

Spinlock is a synchronization technique that occupies the CPU and continues to attempt to acquire the lock until the thread enters the critical section.

  • **Principle of operation: ** is implemented in a busy-waiting method that continuously checks the status of the lock variable, and does not have a wait queue in this process.
  • ** Context Switching:** Context switching for waiting threads does not occur because scheduling support is not provided by the operating system.
  • Advantages and Disadvantages: There is no context exchange cost for the process to sleep and wake up, so it is very efficient in situations where it is possible to enter the critical section quickly. However, since the CPU is constantly consumed while waiting for a lock, if the waiting time is long, system resources may be wasted.
acquire_lock:
    mov eax, 1
    xchg eax, [lock_var]
    test eax, eax
    jnz acquire_lock
    ret

release_lock:
    mov dword [lock_var], 0
    ret

Mutex

Mutex is a mutual exclusion technique that gives up possession of CPU and switches to a waiting state when a thread cannot acquire the lock.

  • Principle of operation: If there is a thread using a shared resource, other threads enter the sleep state while waiting to obtain the lock and are sent to the wait queue. Afterwards, when the lock is released, it wakes up and attempts to acquire the lock.
  • ** Ownership: ** Mutex uses a locking mechanism, so only the process or thread that locks and enters the critical section can unlock the lock.
  • Advantages and Disadvantages: CPU cycles are not wasted while waiting, but it is structurally heavier than a spinlock because it incurs kernel calls and context exchange costs that cause the process to sleep and wake up. Therefore, it is suitable when the work in the critical section is long or when you do not know when it will end.
void mutex_lock(mutex_t *m){
    if (atomic_compare_and_swap(&m->state, 0, 1) != 0) {
        add_to_wait_queue(current_thread, m);
        block();
    }
}

void mutex_unlock(mutex_t *m){
    m->state = 0;
    if (!is_empty(m->wait_queue)) {
        thread_t *t = remove_from_wait_queue(m);
        wakeup(t);
    }
}

Other Synchronization Mechanisms: Semaphores

In addition to spinlocks and mutexes, semaphores are a commonly used technique.

  • Concept: A semaphore is a technique that allows one or more processes or threads to access shared resources using integer variables.
  • Difference from ** mutex: ** mutex allows only one thread to enter the critical section at the same time, and only the person holding the lock can release it. The difference is that a semaphore can allow simultaneous access up to a set integer value (N), and other processes that have not acquired the lock can also attempt to unlock it.