← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Mutex & Locking

Concurrency Intermediate
debt(d9/e5/b5/t7)
d9 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'silent in production until users hit it' (d9). The detection_hints note automated=no and only a regex pattern for flock(). None of the misuses — failing to release in a finally block, using flock() as a distributed lock, or holding locks too long — produce compile-time or lint-time errors. Race conditions and lock leaks are silent until users encounter data corruption or hangs under load in production.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix lists three distinct remediation actions: wrapping releases in finally blocks, replacing flock() with Redis SET NX EX for distributed scenarios, and setting lock timeouts. The flock()-to-Redis migration in particular requires introducing a new dependency, updating configuration, and changing lock acquisition/release logic across all locking sites — more than a single-line swap but not necessarily a full architectural rework.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). Locking applies across web, cli, and queue-worker contexts, meaning any shared-state operation in all three runtime environments must account for the locking strategy. A wrong choice (e.g., flock() in a multi-server environment) silently misbehaves everywhere, and the correct distributed-lock pattern must be consistently applied. It is not quite load-bearing across the entire system shape (b7) but imposes meaningful ongoing discipline across many work streams.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7). The canonical misconception is explicit: developers familiar with mutex/locking concepts from single-server or OS contexts reasonably expect flock() to provide mutual exclusion across a PHP-FPM cluster, but it is per-server only. This directly contradicts reasonable expectations drawn from the concept's name and from how similar primitives work in other languages/environments, making it a serious trap rather than merely a documented gotcha.

About DEBT scoring →

TL;DR

A mutex (mutual exclusion lock) ensures only one thread/process can access a critical section at a time — the fundamental primitive for preventing race conditions.

Explanation

Mutex: binary lock — locked or unlocked. Only the holder can unlock it. Critical section: code protected by the mutex. In PHP: flock() for file-based mutex, Redis SET NX EX for distributed mutex, database advisory locks (GET_LOCK in MySQL). Key properties: atomicity of lock/unlock, single-owner, blocking (waits) vs non-blocking (returns false if unavailable). Distributed systems need distributed locks (Redis Redlock, ZooKeeper, DB advisory locks) since file locks only work within one server. Deadlock risk: never hold mutex A while acquiring mutex B (or maintain consistent order). Release in finally to ensure unlock even on exception.

Common Misconception

flock() provides a distributed lock across multiple servers — flock() is per-server only. Multiple PHP-FPM servers need Redis or DB-based distributed locking.

Why It Matters

Mutexes are the foundation of concurrent programming correctness — without them, any shared mutable state is a potential race condition.

Common Mistakes

  • Not releasing mutex in a finally block — lock held forever on exception.
  • Using flock() as a distributed lock across multiple servers — doesn't work.
  • Holding a mutex too long — reduces concurrency, increases contention.

Code Examples

✗ Vulnerable
$fp = fopen('lock.txt', 'c');
flock($fp, LOCK_EX);
doWork(); // Exception here leaves lock held forever!
flock($fp, LOCK_UN);
fclose($fp);
✓ Fixed
// Always release in finally:
$fp = fopen('lock.txt', 'c');
try {
    flock($fp, LOCK_EX);
    doWork();
} finally {
    flock($fp, LOCK_UN);
    fclose($fp);
}

// Distributed mutex via Redis:
$acquired = $redis->set('lock:job', 1, ['NX', 'EX' => 30]);
if (!$acquired) return; // Another process holds it
try { doWork(); } finally { $redis->del('lock:job'); }

Added 23 Mar 2026
Views 144
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 2 pings W 0 pings T 0 pings F 0 pings S 0 pings S 3 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 2 pings F 1 ping S 0 pings S 0 pings M 0 pings T 1 ping W 1 ping T 0 pings F
No pings yet today
PetalBot 1
Perplexity 16 Amazonbot 14 Scrapy 14 Google 8 Ahrefs 7 SEMrush 7 Bing 6 PetalBot 6 Unknown AI 5 ChatGPT 4 Claude 3 Applebot 2 Majestic 1 Meta AI 1 You.com 1 Twitter/X 1 Sogou 1 Brave Search 1
crawler 93 crawler_json 3 pre-tracking 2
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
Thread concurrency A thread is the smallest unit of execution that your operating system can schedule. Multiple threads within the same program can run at the same time, sharing memory but each following its own sequence of instructions.

Threads let programs do multiple things simultaneously—keeping interfaces responsive, processing requests in parallel, and using multi-core CPUs effectively. Understanding threads is essential for writing fast, responsive software.

💡 If two threads touch the same variable and at least one writes, protect it with a lock—no exceptions.

Ask Codex about Thread →
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Always release locks in finally blocks. Use Redis SET NX EX for distributed locks. Set timeouts on locks to prevent indefinite holds.
📦 Applies To
web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
flock\(|LOCK_EX
Auto-detectable: ✗ No
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-662


✓ schema.org compliant