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

Mutex vs Semaphore

Concurrency CWE-362 PHP 7.0+ Advanced
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 field explicitly states automated=no and the code_pattern is a check-then-modify on shared resource without locking. There is no static analysis tool listed that can catch this; race conditions only manifest under concurrent load and typically surface as data corruption, duplicate records, or double charges in production — not in local or single-process testing.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix points to Redis SETNX as the solution, but adopting distributed locking requires identifying all shared-resource access points, wrapping them with acquire/release logic using try/finally, setting appropriate TTLs, and potentially replacing existing flock-based approaches. This is more than a single-line swap but unlikely to be a full cross-cutting architectural rework unless the pattern is pervasive.

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

Closest to 'persistent productivity tax' (b5). The applies_to scope covers web, cli, and queue-worker contexts — essentially all PHP execution models. Once distributed locking is introduced, every future developer touching shared-resource operations must understand the locking strategy, TTL configuration, and exception-safe release patterns. This imposes ongoing cognitive overhead across multiple work streams without being fully architectural.

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

Closest to 'serious trap (contradicts how a similar concept works elsewhere)' (t7). The misconception field explicitly states that developers believe PHP is single-threaded so mutexes don't apply — a plausible and common assumption for those familiar with single-process PHP scripts. PHP-FPM's multi-process model contradicts this mental model entirely. Combined with the common mistake of using flock for distributed coordination (which works in other single-server languages/contexts), this is a serious trap that catches competent developers who reason from correct-but-incomplete premises.

About DEBT scoring →

Also Known As

mutex PHP distributed lock Redis SETNX semaphore PHP race condition lock

TL;DR

A mutex allows only one thread to access a resource at a time — a semaphore controls access to a pool of N identical resources.

Explanation

A mutex (mutual exclusion) is a binary lock — one owner at a time, the same thread must unlock it. A semaphore is a counter — initialised to N, decremented on acquire, incremented on release; N threads can access the resource concurrently. Binary semaphore (N=1) differs from mutex because any thread can release it. In PHP, true thread-level mutexes require pthreads or Swoole. For web applications, Redis-based distributed locks (SETNX with expiry) serve as mutex equivalents across processes.

Common Misconception

PHP is single-threaded so mutexes don't apply. PHP-FPM runs multiple worker processes concurrently — they share a database and cache, making race conditions very real without process-level locking.

Why It Matters

Without mutual exclusion, two processes can simultaneously modify shared state — corrupting data, double-charging customers, or creating duplicate records.

Common Mistakes

  • Using PHP file locks (flock) for distributed coordination — only works on a single server.
  • Forgetting to release the lock on exception — use try/finally to guarantee release.
  • Setting lock TTL too short — the operation completes after the lock expires, allowing a second process to acquire it mid-operation.

Avoid When

  • Do not use file-based locks (flock) in multi-server deployments — they only work on a single machine.
  • Avoid long lock hold times — keep the critical section as short as possible to reduce contention.

When To Use

  • Use a distributed mutex when multiple PHP workers could race to process the same resource — orders, payments, job dispatching.
  • Use a semaphore when you need to limit concurrency to N workers — e.g. at most 3 concurrent exports.

Code Examples

✗ Vulnerable
// No locking — two workers process the same order simultaneously
if (getOrderStatus($orderId) === 'pending') {
    // Another worker may pass this check at the same moment
    processOrder($orderId); // double processing
}
✓ Fixed
// Redis distributed mutex via Predis
$lockKey = 'lock:order:' . $orderId;
$lockValue = bin2hex(random_bytes(16)); // unique per acquisition
$acquired = $redis->set($lockKey, $lockValue, 'NX', 'EX', 10); // 10s TTL
if (!$acquired) {
    throw new \RuntimeException('Could not acquire lock');
}
try {
    processOrder($orderId);
} finally {
    // Only release if we own the lock
    if ($redis->get($lockKey) === $lockValue) {
        $redis->del($lockKey);
    }
}

Added 31 Mar 2026
Edited 5 Apr 2026
Views 66
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 2 pings T 0 pings W 0 pings T 0 pings F 0 pings S 2 pings S 1 ping M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 1 ping T 1 ping W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Perplexity 9 Amazonbot 7 Ahrefs 5 Scrapy 5 Google 3 PetalBot 3 Unknown AI 2 Twitter/X 2 Meta AI 1 Majestic 1 Brave Search 1 Applebot 1
crawler 38 crawler_json 2
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Use Redis SETNX (SET ... NX EX) for distributed mutex locking in PHP web applications — pthreads is not available in standard PHP-FPM
📦 Applies To
PHP 7.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
check-then-modify pattern on shared resource without locking
Auto-detectable: ✗ No
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: High Context: File Tests: Update
CWE-362


✓ schema.org compliant