πŸ“Œ Spinlock

Spinlock β€” простой ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ синхронизации, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½Ρ‹Ρ… ΠΈ ΠΌΡƒΠ»ΡŒΡ‚ΠΈΠΏΡ€ΠΎΡ†Π΅ΡΡΠΎΡ€Π½Ρ‹Ρ… систСмах для Π·Π°Ρ‰ΠΈΡ‚Ρ‹ раздСляСмых рСсурсов. ΠŸΡ€ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ спинлок ΠΏΠΎΡ‚ΠΎΠΊ (ΠΈΠ»ΠΈ процСссор) ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ провСряСт Π΄ΠΎΡΡ‚ΡƒΠΏΠ½ΠΎΡΡ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π² Ρ†ΠΈΠΊΠ»Π΅ оТидания (spin), Π½Π΅ пСрСходя Π² состояниС сна. Π’Π°ΠΊΠΎΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ эффСктивСн для ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΡ… критичСских сСкций ΠΈ Π² систСмах с высокой ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ†ΠΈΠ΅ΠΉ Π·Π° рСсурсы, Π³Π΄Π΅ ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ контСкста дорогостоящо.


🧠 Как Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚

ΠœΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Ρ€Π°Π±ΠΎΡ‚Ρ‹

  • ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° Π·Π°Ρ…Π²Π°Ρ‚Π°: ΠΏΠΎΡ‚ΠΎΠΊ пытаСтся ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ„Π»Π°Π³Π° Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, atomic test-and-set ΠΈΠ»ΠΈ compare-and-swap).
  • ЦикличСскоС ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅: Ссли Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° занята, ΠΏΠΎΡ‚ΠΎΠΊ Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π² Ρ†ΠΈΠΊΠ» ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ, повторяя ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ Π·Π°Ρ…Π²Π°Ρ‚Π° (спин).
  • ОсвобоТдСниС: Π²Π»Π°Π΄Π΅Π»Π΅Ρ† Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ снимаСт Ρ„Π»Π°Π³, позволяя Π΄Ρ€ΡƒΠ³ΠΈΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ спинлок.
  • ΠŸΡ€Π΅ΠΈΠΌΡƒΡ‰Π΅ΡΡ‚Π²Π°: Π½Π΅Ρ‚ расходов Π½Π° ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ контСкста, Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠ° минимальна ΠΏΡ€ΠΈ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΡ… критичСских сСкциях.
  • НСдостатки: потСря процСссорного Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΏΡ€ΠΈ Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΌ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ (busy-wait).

Π‘Π»ΠΎΠΊ-схСма

flowchart TB
    CPU["CPU / Thread"]
    Spinlock["Spinlock (atomic_flag)"]
    Memory["Shared Memory / Resource"]

    CPU -->|ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° Π·Π°Ρ…Π²Π°Ρ‚Π°| Spinlock
    Spinlock -- Busy wait --> CPU
    Spinlock -->|Доступ Ρ€Π°Π·Ρ€Π΅ΡˆΡ‘Π½| Memory
    CPU -->|Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ критичСской сСкции| Memory
    CPU -->|ОсвобоТдСниС| Spinlock

    style Spinlock stroke:#fff,stroke-width:5px,font-weight:bold

ΠšΠ»ΡŽΡ‡Π΅Π²Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ

  • lock(spinlock) β€” ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ° Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ, Π·Π°Ρ†ΠΈΠΊΠ»ΠΈΠ²Π°ΡΡΡŒ, ΠΏΠΎΠΊΠ° ΠΎΠ½Π° Π½Π΅ станСт свободна.
  • unlock(spinlock) β€” освобоТдСниС Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ.
  • Atomic primitives β€” тСст ΠΈ установка значСния, Π²Π°ΠΆΠ½Π° Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΡΡ‚ΡŒ для прСдотвращСния Π³ΠΎΠ½ΠΎΠΊ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠ° (псСвдокод)

function lock(spinlock):
    while atomic_test_and_set(spinlock) == LOCKED:
        ; // Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ ΠΆΠ΄Π΅ΠΌ (spin)
 
function unlock(spinlock):
    atomic_clear(spinlock)

Π’Π°ΠΆΠ½Ρ‹Π΅ Π΄Π΅Ρ‚Π°Π»ΠΈ

  • ΠΡ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΡΡ‚ΡŒ: ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π·Π°Ρ…Π²Π°Ρ‚Π° ΠΈ освобоТдСния Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹ΠΌΠΈ.

  • ΠŸΡ€Π΅ΠΈΠΌΡƒΡ‰Π΅ΡΡ‚Π²ΠΎ для SMP: Ρ…ΠΎΡ€ΠΎΡˆΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π½Π° систСмах с нСсколькими процСссорами.

  • ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ΠΎΠ²: Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° β€œΠ³ΠΎΠ»ΠΎΠ΄Π°Π½ΠΈΡβ€ (starvation).

  • ИспользованиС Π² ОБ: ядро Linux Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ примСняСт спинлоки для синхронизации Π² SMP.

  • Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ кэшами: соврСмСнныС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΡŽΡ‚ спинлок с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ инструкций ΠΏΠ°ΡƒΠ·Ρ‹ (pause/yield), ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Ρ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ Π½Π° кэш.


βš™οΈ Π“Π΄Π΅ примСняСтся

  • Бинхронизация Π² ядрС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Ρ… систСм.

  • Π’ систСмах Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ с минимальной Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ.

  • Π’Ρ‹ΡΠΎΠΊΠΎΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹Π΅ вычислСния.

  • Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ раздСляСмыми рСсурсами Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½Ρ‹Ρ… прилоТСниях.

  • ВстраиваСмыС ΠΈ Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹Π΅ систСмы с ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π½ΠΎΠΉ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°.


βœ… ΠŸΡ€Π΅ΠΈΠΌΡƒΡ‰Π΅ΡΡ‚Π²Π°

  • ΠœΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ Π½Π°ΠΊΠ»Π°Π΄Π½Ρ‹Π΅ расходы ΠΏΡ€ΠΈ ΠΊΡ€Π°Ρ‚ΠΊΠΈΡ… критичСских сСкциях.

  • ΠŸΡ€ΠΎΡΡ‚ΠΎΡ‚Π° Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

  • Π₯ΠΎΡ€ΠΎΡˆΠ°Ρ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Π½Π° SMP-систСмах.

  • НС Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ контСкста.

  • ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ быстрыС Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π² ядрС ОБ.


❌ НСдостатки

  • ΠŸΠΎΡ‚Π΅Ρ€Ρ процСссорного Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΏΡ€ΠΈ Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΌ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ.

  • НСэффСктивСн Π½Π° однопроцСссорных систСмах.

  • Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ β€œΠ³ΠΎΠ»ΠΎΠ΄Π°Π½ΠΈΡβ€ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ².

  • ВысокоС энСргопотрСблСниС ΠΈΠ·-Π·Π° Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ оТидания.

  • Π’Ρ€Π΅Π±ΡƒΠ΅Ρ‚ остороТного использования для прСдотвращСния Π΄Π΅Π΄Π»ΠΎΠΊΠΎΠ².


πŸ”— БвязанныС Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ

Mutex, Semaphore, Atomic Operation, Lock-Free, Barrier, SMP, Preemption, RTOS, Linux Kernel Synchronization, Futex


РСзюмС

Spinlock β€” Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ с Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΌ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ΠΌ, примСняСмый для Π·Π°Ρ‰ΠΈΡ‚Ρ‹ ΠΊΡ€Π°Ρ‚ΠΊΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… критичСских сСкций Π² многопроцСссорных систСмах. ΠžΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°Π΅Ρ‚ Π½ΠΈΠ·ΠΊΠΈΠ΅ Π½Π°ΠΊΠ»Π°Π΄Π½Ρ‹Π΅ расходы ΠΈ простоту, Π½ΠΎ Π½Π΅ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ для Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ оТидания, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ процСссор Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΌ Ρ†ΠΈΠΊΠ»ΠΎΠΌ. ΠšΠ»ΡŽΡ‡Π΅Π²ΠΎΠΉ элСмСнт синхронизации Π² ядрах ОБ ΠΈ систСмах с высокой ΡΡ‚Π΅ΠΏΠ΅Π½ΡŒΡŽ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ·ΠΌΠ°.


ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ΠΊΠΎΠ΄Π°

C: простой спинлок Π½Π° atomic_flag (C11)

#include <stdatomic.h>
 
typedef struct {
    atomic_flag flag;
} spinlock_t;
 
void spinlock_init(spinlock_t *lock) {
    atomic_flag_clear(&lock->flag);
}
 
void spinlock_lock(spinlock_t *lock) {
    while (atomic_flag_test_and_set_explicit(&lock->flag, memory_order_acquire)) {
        // active wait (spin)
    }
}
 
void spinlock_unlock(spinlock_t *lock) {
    atomic_flag_clear_explicit(&lock->flag, memory_order_release);
}

C++: использованиС std::atomic_flag

#include <atomic>
 
class SpinLock {
    std::atomic_flag flag = ATOMIC_FLAG_INIT;
public:
    void lock() {
        while(flag.test_and_set(std::memory_order_acquire)) {
            // spin
        }
    }
    void unlock() {
        flag.clear(std::memory_order_release);
    }
};

АссСмблСр x86: инструкция LOCK CMPXCHG для Π·Π°Ρ…Π²Π°Ρ‚Π° спинлока

spin_lock:
    mov eax, 0          ; ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (0 - свободно)
try_lock:
    mov ebx, 1          ; Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ (1 - занято)
    lock cmpxchg [lock_var], ebx
    jne try_lock        ; Ссли Π½Π΅ ΡƒΠ΄Π°Π»ΠΎΡΡŒ Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ β€” ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΠΈΡ‚ΡŒ
    ret

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊΠΈ:
Linux Kernel Documentation, Intel x86 Architectures Manuals, C11 standard, C++11 std::atomic, OSDev.org, Wikipedia, β€œOperating Systems: Three Easy Pieces” by Remzi & Andrea Arpaci-Dusseau.