A deadlock is when you go home one day and you stick a key in the lock, and the key breaks, so you ask the lock picker to pick the lock, and the lock dies. That’s a deadlock. That’s just a joke, but let’s get to the point.
What is a deadlock?
To understand what a deadlock is, it’s important to understand what a lock is for. Locking in Java is basically about keeping resources safe and ensuring that only one thread at a time changes a shared resource. (The above is for personal understanding only, if you have any questions, please comment.) The concept of a deadlock is easy to understand. It is a deadlock caused by two or more threads competing for the same resource, and neither of the two threads gives in, and there is no external coordination.
Example 1: There is only one lane on the road, just when two cars arrived, the two drivers began to quarrel, saying that I was there first, neither of them gave way, and there was no traffic police to coordinate on the road, so the two drivers quarreled. This example is biased, of course, but serves as a primer.
Example 2: A deadlock in a thread is:
Thread A -> lock resource A -> lock resource B
Thread B -> lock RESOURCE B -> lock resource A
As A result, both threads are started at the same time, causing thread A to hold on to resource A and request resource B, while thread B holds on to resource B and request resource B.
The two examples above correspond to two causes of thread deadlocks.
Cause of deadlock
Two reasons:
1. Competition for resources cannot deprive resources
2. Process sequence conflicts
Just a bit similar to the above two examples, the reader can review it.
Four necessary conditions for deadlock
1. Mutually exclusive conditions. Processes require exclusive control over allocated resources, that is, the resources can be used by only one process at a time.
2. Request and hold, that is, the process holds on to acquired resources and keeps requesting new resources, like a greedy person eating from the bowl and looking into the pot.
3. Inalienable, the resource can only be released now, but the greedy person’s name on the property certificate is him.
4. Loop waiting conditions, closed loop, guys, what he wants is his wife’s, his wife wants his house ownership certificate.
Basic approach to deadlock resolution
The basic idea is to avoid deadlocks and how to resolve them if they occur.
Prevent deadlocks:
The prevention of deadlocks is to destroy the necessary conditions for the occurrence of deadlocks.
1. Allocate all resources at once, and give everything you need directly. (Failure condition 2)
2. As long as one resource is not allocated, other resources are also not allocated. (Failure condition 2)
3. Deprivable resources: when a process obtains some resources but not others, it releases the occupied resources (break condition 3)
4. Resource order: The system allocates numbers to each type of resources in an orderly manner. Processes request resources according to these numbers, and release locks in reverse order (Condition 4)
What are the options for preventing deadlocks?
Option 1: Release over time (breaking inalienable conditions)
Synchronized direct PASS, which blocks unless requested. So what we need is a LOCK that can be manually released to release the LOCK. You can use the timeout period in tryLock directly to release the lock.
Scheme 2: Obtain locks in a planned sequence (break loop wait condition)
To avoid the second example above, avoid end to end, according to the planned sequence of obtaining locks to obtain resources, need to plan according to the specific scene.
Deadlock detection
1. Jstack command
Jstack is used to generate a thread snapshot of the Java VIRTUAL machine at the current time. A thread snapshot is a collection of method stacks that are being executed by each thread in the Java VIRTUAL machine (JVM). The main purpose of a thread snapshot is to locate the cause of a long pause in a thread, such as deadlocks, loops, and long waits caused by requests for external resources. By looking at the call stack of each thread when it pauses, you can see what the unresponsive thread is doing in the background, or what resources it is waiting for. If a Java program crashes to generate a core file, the JStack tool can be used to get information about the Java Stack and native stack of the core file, so you can easily know how the Java program crashed and where the problem occurred in the program. In addition, the JStack tool can attach to a running Java program and see information about the Java Stack and native Stack of the running Java program. Jstack is very useful if the current running Java program appears hung.
The above Jstack command references the blog
2. JConsole tool
JConsole is a built-in Java performance analyzer that can be run from the command line (type JConsole directly) or in a GUI shell (open under JDK \bin).
It is used to monitor memory, threads, classes, and so on in the JVM. You can use the JTop plug-in. It can monitor local JVMS, remote JVMS, and several JVMS simultaneously.
The benefit of this tool is that it consumes less system resources and, combined with Jstat, can effectively monitor changes in Java memory and why they occur. Useful when tracking memory leaks in a project.
The above JConsole tool references blogs