Spinlocks vs. Semaphores: Understanding Synchronization Mechanisms
Deepesh Menon
Principal Engineer | Heterogeneous Computing Systems | Virtualization | Embedded Systems
Synchronization mechanisms are essential for managing concurrent access to shared resources in modern computing. Two of the most commonly discussed synchronization primitives are spinlocks and semaphores. While they may serve overlapping purposes, their behavior, implementation, and use cases differ significantly.
This article explores the key differences between spinlocks and semaphores, diving into their low-level implementations on architectures like ARM and x86, and addressing the historical concepts of P and V operations in semaphores.
Disclaimer: The code snippets provided in this article are for quick reference and conceptual understanding only. They have not been compiled or tested and should be treated as high-level pseudocode rather than production-ready implementations. Use them as a guide to understand the underlying concepts, not as exact implementations.
What Are Spinlocks?
Spinlocks are lightweight synchronization mechanisms primarily used for protecting critical sections. They work by continuously checking (spinning) a shared lock variable until it becomes available.
Key Characteristics of Spinlocks:
Modern Optimizations on ARM:
To reduce CPU resource wastage, modern ARM architectures use WFE (Wait For Event) instructions to temporarily put the core into a low-power state if the lock is unavailable. This optimization:
Example Spinlock Implementation (ARM):
acquire_spinlock:
LDREX r0, [lock_var] // Load the lock value
CMP r0, #0 // Check if the lock is free
BNE wait_for_event // If not free, wait
STREX r1, r2, [lock_var] // Try to acquire the lock
CMP r1, #0 // Check if STREX succeeded
BNE acquire_spinlock // Retry if failed
DMB // Memory barrier
BX lr // Return
wait_for_event:
WFE // Wait for an event
B acquire_spinlock // Retry acquiring the lock
What Are Semaphores?
Semaphores are more versatile synchronization primitives that use a counter to manage access to shared resources. They can block threads if a resource is unavailable.
Key Characteristics of Semaphores:
领英推荐
Semaphore Operations: P and V
The fundamental operations on a semaphore are often referred to as P and V, terms introduced by Edsger Dijkstra:
These terms, though less common in modern APIs, reflect the theoretical underpinnings of semaphores and emphasize their purpose.
Example Semaphore Wait and Signal:
void semaphore_wait(int *sem) {
while (1) {
int val = ldrex(sem); // Load semaphore value
if (val > 0) {
if (strex(sem, val - 1) == 0) // Decrement if available
break; // Success
} else {
block_thread(); // Scheduler blocks the thread
}
}
}
void semaphore_signal(int *sem) {
while (1) {
int val = ldrex(sem); // Load semaphore value
if (strex(sem, val + 1) == 0) // Increment the count
break;
}
wake_thread(); // Wake a blocked thread, if any
}
Key Differences Between Spinlocks and Semaphores
When to Use Spinlocks vs. Semaphores
Conclusion
Both spinlocks and semaphores are critical tools in concurrent programming, but their use depends on the context:
Understanding the trade-offs between these synchronization primitives—and the conceptual meaning of operations like P and V—is essential for designing efficient and scalable systems. Whether you're working in embedded systems, operating system design, or application-level concurrency, knowing when to use each mechanism is key to optimizing performance.
Principal Engineer | Heterogeneous Computing Systems | Virtualization | Embedded Systems
3 个月Torsten Robitzki , Kai Lampka, Dr.-Ing. (habil.) this article is specifically oriented toward semaphore. In my previous articles I have detailed about Mutex and Spinlocks. Spinlocks : https://www.dhirubhai.net/pulse/understanding-spinlocks-how-cpu-supports-atomic-locks-p-m-f9xhc?utm_source=share&utm_medium=member_android&utm_campaign=share_via Mutex locks: https://www.dhirubhai.net/pulse/operating-system-synchronization-primitives-mutex-locks-p-m-beu2c?utm_source=share&utm_medium=member_android&utm_campaign=share_via
Shouldn't it be Mutexes vs. Semaphores and sleep wait vs. busy wait?
Torrox GmbH & Co. KG
3 个月Simply: Don't use spinlocks unless, you really, really know what you are doing. If you are using spinlocks in an IRQ, making sure, that a critical section of code can not be seen with invariants broken, who is going to release that lock, in case, it is found to be locked? If there is only one CPU involved, it can only be an IRQ with higher priority. So, the use of spinlocks in a single CPU system, is very little, if any. For semaphores, there must be at least some kind of scheduler involved. I also would not bet on a semaphore implementations to be "fair", as this usually increases complexity of the implementation and reduces performance.