Mutex (Mutual Exclusion Lock) là binary lock: chỉ có 2 trạng thái locked/unlocked, và quan trọng là chỉ thread nào lock thì mới được unlock (ownership semantics). Dùng để bảo vệ critical section — chỉ 1 thread access vào một lúc.
Semaphore là counter: counting semaphore cho phép N thread cùng access (semaphore=N); binary semaphore (N=1) tương tự mutex nhưng không có ownership — thread A có thể signal semaphore mà thread B đã wait.
Dùng mutex khi: bảo vệ shared data (HashMap, linked list) — một thread đọc/ghi tại một thời điểm. Dùng semaphore khi: giới hạn concurrent access (connection pool tối đa 10 connections), producer-consumer synchronization (producer signal khi có item mới). Deadlock risk: mutex thường dùng recursive mutex để tránh self-deadlock. Go dùng sync.Mutex và sync.RWMutex (nhiều reader, 1 writer); channel thường là cách idiomatic hơn để synchronize trong Go.
A Mutex (Mutual Exclusion Lock) is a binary lock with two states: locked and unlocked. Critically, only the thread that locked it can unlock it (ownership semantics). It is used to protect a critical section, ensuring only one thread accesses it at a time.
A Semaphore is a counter: a counting semaphore allows up to N threads concurrent access (initialized to N); a binary semaphore (N=1) is similar to a mutex but lacks ownership — thread A can signal a semaphore that thread B is waiting on.
Use a mutex when protecting shared data (e.g., a HashMap or linked list) — one thread reads or writes at a time. Use a semaphore when limiting concurrent access (e.g., a connection pool capped at 10 connections) or for producer-consumer synchronization (producer signals when a new item is available). Deadlock risk: recursive mutexes are often used to prevent self-deadlock. Go provides sync.Mutex and sync.RWMutex (multiple concurrent readers, one writer); channels are generally the more idiomatic way to synchronize in Go.