4.4 Common Problems in Synchronization Deadlock A deadlock is a situation where two or more tasks are blocked forever, each waiting for a resource that is held by another task in the cycle. Example Deadlock Scenario: Task A successfully locks Mutex 1. Task B successfully locks Mutex 2. Task A now tries to lock Mutex 2, but it must wait because Mutex 2 is held by Task B. Task B now tries to lock Mutex 1, but it must wait because Mutex 1 is held by Task A. Both tasks are now waiting for each other indefinitely, and neither can proceed. The Four Conditions for Deadlock (Coffman's Conditions) : Mutual Exclusion : At least one resource must be non-sharable (can only be used by one task at a time). Hold and Wait : A task holds at least one resource while waiting for another resource held by a different task. No Preemption : A resource cannot be forcibly taken from the task holding it; it can only be released voluntarily. Circular Wait : A circular chain of two or more tasks exists, where each task is waiting for a resource held by the next task in the chain. Priority Inversion Priority inversion is a scenario where a high-priority task is forced to wait for a much lower-priority task. This happens when the low-priority task is holding a lock (e.g., a mutex) that the high-priority task needs. The problem worsens if a medium-priority task starts running, as it will preempt the low-priority task, preventing it from releasing the lock. As a result, the high-priority task never gets a chance to run. Starvation Starvation is a condition where a task is perpetually denied access to the resources it needs to complete its execution. This often happens to low-priority tasks that are constantly being preempted by higher-priority tasks, preventing them from ever getting their slice of CPU time.