Apa itu spinlock?
Spinlock membuat thread menunggu secara aktif (busy-wait) dalam sebuah loop sampai lock tersedia, alih-alih tidur seperti mutex. Selama menunggu, thread terus-menerus mengecek apakah lock sudah bisa diambil dan tidak pernah benar-benar berhenti memakai CPU.
Mutex sebaliknya: menidurkan thread saat menunggu, lalu membangunkannya lagi saat lock dilepas.
Ilustrasi
Mutex: Thread2 gagal lock() → BLOCKED, tidur, CPU bebas → dibangunkan scheduler saat lock dilepas
Spinlock: Thread2 spin_lock() → cek... cek... cek... (CPU sibuk) → dapat begitu lock dilepas
Kenapa kadang lebih baik
Mutex punya overhead: saat thread gagal dapat lock, kernel harus menidurkannya (context switch), lalu membangunkannya lagi nanti (context switch lagi). Ini tidak gratis.
Kalau critical section-nya sangat pendek — misal cuma increment satu variabel — waktu context switch ke sleep dan balik lagi bisa lebih lama dari waktu tunggu itu sendiri. Di sinilah spinlock, yang tidak perlu context switch sama sekali, bisa lebih cepat. Tapi ini cuma masuk akal di kondisi tertentu: multi-core (supaya pemegang lock bisa jalan paralel di core lain) dan critical section super pendek.
Implementasi
Struktur proyek
.
└── spinlock_demo.c
Step 1: program dengan spinlock
Dua thread increment counter yang sama sebanyak 1 juta kali.
#include <pthread.h>
#include <stdio.h>
pthread_spinlock_t spinlock;
long counter = 0;
void *increment(void *arg)
{
for (int i = 0; i < 1000000; i++) {
pthread_spin_lock(&spinlock);
counter++;
pthread_spin_unlock(&spinlock);
}
return NULL;
}
int main(void)
{
pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE);
pthread_t t1, t2;
pthread_create(&t1, NULL, increment, NULL);
pthread_create(&t2, NULL, increment, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Counter akhir: %ld (expected: 2000000)\n", counter);
pthread_spin_destroy(&spinlock);
return 0;
}
Step 2: versi mutex untuk perbandingan
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
long counter = 0;
void *increment(void *arg)
{
for (int i = 0; i < 1000000; i++) {
pthread_mutex_lock(&mutex);
counter++;
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void)
{
pthread_t t1, t2;
pthread_create(&t1, NULL, increment, NULL);
pthread_create(&t2, NULL, increment, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Counter akhir: %ld (expected: 2000000)\n", counter);
return 0;
}
Penjelasan
pthread_spin_lock loop terus-menerus mengecek lock sampai berhasil didapat — tidak pernah menidurkan thread, CPU tetap sibuk selama menunggu. pthread_spin_unlock melepas lock, thread lain yang sedang spin akan mendeteksinya di iterasi berikutnya.
Untuk membandingkan waktu eksekusi kedua versi, tambahkan timing sederhana di main:
#include <time.h>
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
// ... buat & join thread ...
clock_gettime(CLOCK_MONOTONIC, &end);
double elapsed = (end.tv_sec - start.tv_sec) +
(end.tv_nsec - start.tv_nsec) / 1e9;
printf("Waktu: %.4f detik\n", elapsed);
Jalankan versi spinlock dan mutex dengan timing ini untuk melihat perbedaan nyata di mesin kamu — hasilnya bisa beda tergantung jumlah core dan beban sistem saat itu.
Kapan spinlock menang
| Skenario | Spinlock | Mutex |
|---|---|---|
| Critical section sangat pendek, multi-core, low contention | lebih cepat | overhead context switch terasa |
| Critical section panjang (ada I/O, sleep, dsb.) | buang CPU sia-sia | lebih efisien |
| Single-core | hampir selalu lebih buruk | lebih baik |
| Contention tinggi | CPU makin panas, tidak fair | lebih stabil |
Kompilasi
gcc -o spinlock_demo spinlock_demo.c -lpthread
./spinlock_demo
Best practices
Jangan pernah spin di atas operasi yang bisa blocking — I/O, syscall, atau apapun yang berpotensi lama, karena thread lain akan buang CPU cycle tanpa progres. Spinlock cuma masuk akal untuk critical section super pendek, beberapa instruksi CPU, bukan operasi kompleks. Di single-core, spinlock hampir selalu kalah dari mutex, karena thread yang spin tidak memberi kesempatan pemegang lock untuk jalan.
Spinlock juga tidak fair — tidak ada jaminan FIFO, thread bisa starvation kalau contention tinggi dan terus-menerus. Jadi selalu benchmark, jangan asumsi — ukur langsung di mesin dan beban kerja yang relevan.
Kesimpulan
Spinlock itu trade-off: busy-wait yang boros CPU, ditukar dengan menghindari overhead context switch. Cocok untuk critical section yang sangat pendek di sistem multi-core dengan contention rendah, tapi bukan pengganti mutex secara umum — ini alat khusus untuk kasus yang spesifik1.
Footnotes
-
Beberapa implementasi mutex modern, termasuk glibc, sebenarnya sudah menggabungkan strategi ini secara internal — spin sebentar dulu sebelum benar-benar tidur (adaptive mutex) — jadi di banyak kasus, mutex bawaan sistem sudah cukup pintar tanpa perlu spinlock manual. ↩