[Linux] What is deadlock and how to avoid it

Before introducing deadlock, let's talk about the classification of resources in the operating system

Classification of resources in operating systems

  1. Classification according to the number of uses
    (1) Reusable resources

Units in each reusable resource can only be allocated to one process, and multiple threads are not allowed to share.
The sequence of process use of resources:
(1) Request resources, if the request fails, the process blocks or waits in a loop;
(2) Use resources;
(3) Release resources.
The number of reusable resources in the system is relatively fixed and cannot be increased or deleted when the program is running.

(2) Consumable resources

It is a temporary resource that is dynamically created and consumed by the process running. The number of each type of consumable resource unit is constantly changing, usually created in the producer thread and consumed in the consumer thread.

  1. According to whether it can be preempted
    (1) Preemptable resources

Resources that can be shared such as CPU, main memory, etc.

(2) Resources cannot be preempted

Unshareable resources such as printers, CD-ROMs, etc.

What is deadlock?

  1. definition

Thread deadlock means that because two or more threads hold each other's resources, these threads are in a waiting state and cannot go to execution.
When a thread enters the synchronized code block of the object, it occupies the resource, and the resource is not released until it exits the code block or calls the wait method. During this period, other threads will not be able to enter the code block.
When threads hold the resources needed by each other, they will wait for each other to release the resources. If the threads do not actively release the resources they occupy, a deadlock will occur.

  1. Scenarios where deadlock occurs
    (1) Deadlock caused by competition for non-preemptible resources

For example, suppose there are two processes, P1 and P2, both of which need two resources, A and B. Now P1 holds A and waits for B resources, while P2 holds B and waits for A resources. Both wait for another resource and refuse to accept it. Release resources and wait indefinitely like this, which forms a deadlock, which is also a case of deadlock. To define a deadlock, a group of processes is deadlocked if each process in the group is waiting for an event that can only be raised by other processes in the group.

(2) Deadlock caused by competing for consumable resources

There are three processes: p1, p2 and p3, p1 sends messages to p2 and accepts messages from p3, p2 sends messages to p3 and accepts messages from p2, p3 sends messages to p1 and accepts messages from p2, if the setting is to receive first If the message is sent after the message, all the messages cannot be sent, which causes a deadlock.

(3) Deadlock caused by improper execution sequence of threads

There are processes p1 and p2, which all need resources A and B. Originally, p1 could run A –> p1 run B –> p2 run A –> p2 run B, but the order was changed. When p1 runs A, p2 runs B, which is prone to the first A kind of deadlock. grab resources from each other.

(4) Another kind of deadlock: recursive deadlock

The so-called recursive function is a self-invoking function, which directly or indirectly calls itself in the function body, that is, the nesting of the function is the function itself.
There are two types of recursion: direct recursion and indirect recursion. Direct recursion is where the function itself is called in a function. Indirect recursion means that another function is called in the function, and the other function calls this function.
So when to use recursion? Generally, recursion is used when you want to use a loop iteration in a piece of code logic but the number of iterations is not known before the iteration.
For example, if you want to find a file in a folder, and there are N subfolders and files under this folder, you have to use recursion when you don't know how many layers of folders and files there are. .
The advantage of recursion is to make the code look very concise, and some application scenarios have to use recursion, such as finding files as mentioned above.
Recursion is a good thing but can give you some trouble at some point. For example, if you use recursion in a multi-threaded environment, you have to face the problem of synchronization when you encounter multi-threading.
Recursive programs are prone to problems when they encounter synchronization. Multi-threaded recursion means that a method in the recursive chain is operated by another thread. (If it is in a thread, there is no deadlock problem)

Let's summarize the four necessary conditions for deadlock to occur

Four necessary conditions for deadlock

1. Mutual exclusion conditions

The process is exclusive to the allocated resources, that is, a resource can only be occupied by one process until it is released by the process

2. Request and Hold Conditions

When a process is blocked due to a request for an occupied resource, it keeps the acquired resource.

3. No deprivation conditions

Before any resource is released by the process, no other process can deprive it of occupation

4. Circular wait condition

When a deadlock occurs, the waiting processes must form a loop (similar to an infinite loop), causing permanent blocking.

How to avoid deadlock

Let's explain how to avoid deadlocks
1. Prevent deadlocks
The four necessary conditions for deadlocks have been introduced above. How to avoid deadlocks? As long as one of the four necessary conditions above is violated, no deadlock will occur.
2. Avoid deadlock
In the process of dynamic resource allocation, use some method to prevent the system from entering an unsafe state, thereby avoiding deadlock.

Deadlock prevention and deadlock avoidance are both pre-prevention strategies, but the restrictions on deadlock prevention are relatively strict and simple to implement, but often lead to low system efficiency and low resource utilization;
the restrictions on deadlock avoidance are relatively loose. After resource allocation, it is necessary to use an algorithm to determine whether to enter an unsafe state, which is more complicated to implement.

3. Detection of deadlock
This method does not need to take any restrictive measures in advance, and it is not necessary to check whether the system has entered an unsafe area. This method allows the system to deadlock during operation. However, the detection mechanism set by the system can detect the occurrence of deadlock in time, and accurately determine the processes and resources related to the deadlock, and then take appropriate measures to clear the deadlock that has occurred from the system.
4. Unlock deadlock
This is a measure that is matched with detection of deadlock. When it is detected that a deadlock has occurred in the system, the process must be released from the deadlock state. A common implementation method is to revoke or suspend some processes in order to reclaim some resources, and then allocate these resources to the processes that are already in the blocked state and make them ready to continue running. Deadlock detection and removal measures may enable the system to obtain better resource utilization and throughput, but it is also the most difficult to achieve.

  • Deadlock handling strategies
    Deadlock handling strategies: ostrich strategy, prevention strategy, avoidance strategy, detection and recovery strategy
  • Three techniques to avoid deadlock
    (1) Lock sequence
    (2) Lock time limit
    (3) Deadlock detection
    Refer to this blog post
  • Common Algorithms
    Banker 's Algorithm
    Refer to this blog post

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324808558&siteId=291194637
Recommended