Deadlocks can only occur if all four specific conditions are met. Therefore, strategies to prevent deadlocks focus on negating one of these conditions.
Condition | Description | Solutions | Dangers |
Mutual Exclusion / Mutex | When resources can't be used by mutual thread and there are less resources than threads. | 1) Use concurrently accessible resources like AtomicInteger. 2) Increase the number of resources until its greater or equal to the number of competing threads. 3 ) Check if every required resource is accessible before the task starts. | |
Lock & Wait | Once a thread acquires a resource, it will not release the resource until it has acquired all of the other resources it requires and has completed its work. | Before reservation of a resource, check its accessibility. If a resource is not accessible, release every resource and start from anew. |
- Starvation: A thread never achieves to reserve all required resources. 2) Livelock: Thread gets tangled up.
These two approach are always applicable but inefficient as it causes a bad performance. | | | | | | | | | | |
Lock & Wait
- Description:
- Once a thread acquires a resource, it will not release the resource until it has acquired all of the other resources it requires and has completed its work.
- Solutions:
- Before reservation of a resource, check its accessibility.
- If a resource is not accessible, release every resource and start from anew.
- Dangers:
- Starvation: A thread never achieves to reserve all required resources.
- Livelock: Thread gets tangled up.→ This approach is always applicable but inefficient as it causes a bad performance.
No preemption
- Description:
- A thread is unable to steal a resources reserved by another thread.
- Solution:
- A thread is allowed to ask another thread to release all of its resources (including the required one) and starting from anew. This approach is similar to the 'Lock & Wait' solution but has a better performance.
Circular Waiting / Deadly Embrace
- Description:
- When two or more threads require a resource which is already reserved by another of these threads.
- Example:
- Thread T1 has resource R1 and waits for R2 to be released.
- Thread T2 has resource R2 and waits for R1 to be released.
- Solution:
- All threads reserve all resources in a the same order.
- Problems:
- The order of reservation doesn't necessarily have to be the same as the order of usage. This leads to inefficiencies like reserving a resource at the beginning which is just required at the end of the task.
- Unnecessarily long locked resources.
- Order can not always be specified.