SwiftQA Random

What is priority inversion?

The core scenario

Priority inversion happens when a high-priority task is blocked waiting on a resource held by a low-priority task, and that low-priority task gets delayed because the scheduler keeps running medium-priority work instead.

High priority task:    waiting for lock ──────────────────────▶ (blocked the whole time)
Low priority task:     holds lock ──X (preempted, never releases lock)
Medium priority tasks: ████████████████████████████████ (keep running, since they outrank Low)

Why this matters concretely on iOS

The classic example is the Mars Pathfinder incident (1997). On iOS, this shows up as: a .background/.utility QoS task holding a lock a .userInteractive task needs — resulting in unexplained UI jank/hangs.

The classic mitigation: priority inheritance

The scheduler temporarily boosts the lock-holder’s priority to match the highest-priority waiter. NSLock/pthread_mutex have some priority inheritance behavior; DispatchSemaphore notably does not.

How Swift’s concurrency model changes (but doesn’t eliminate) this

Task priority inheritance/escalation; actors process work without the traditional lock-holding pattern, though not immune if a low-priority task occupies an actor’s turn.

Why this is another “compiler can’t catch it” bug class

Same category as deadlocks and reentrancy — about scheduling behavior and timing, not aliasing or data races.

One-liner if pressed: “Priority inversion is when a high-priority task is blocked on a resource held by a low-priority task, and that low-priority task can’t finish because medium-priority work keeps preempting it. The classic fix is priority inheritance — Apple’s mutex primitives do this to a degree (though DispatchSemaphore doesn’t), and Swift’s Task scheduler has some built-in escalation — but it’s a scheduling/timing problem the compiler has no visibility into.”