Synchronization primitive is a mechanism for coordinating access to shared state between concurrent threads or processes, preventing race conditions. Primitives split into mutual exclusion (e.g., Mutex), which ensures only one thread accesses data at a time, and communication/coordination (e.g., Semaphore, CSP), which lets threads signal each other.
All synchronization primitives ultimately rely on hardware atomics (compare-and-swap) and the OS scheduler's ability to block and wake threads.
This example shows a mutex protecting shared data from race conditions.
// compile: gcc -pthread -o sync sync.c // run: ./sync // description: mutex prevents concurrent access to shared counter #include <pthread.h> #include <stdio.h> int counter = 0; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; void* increment(void* arg) { for (int i = 0; i < 100000; i++) { pthread_mutex_lock(&lock); counter++; pthread_mutex_unlock(&lock); } return NULL; } int main() { 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: %d\n", counter); return 0; }