Java deadlock code demonstration

The concept of deadlock

Knowledge reserves

Object lock: Everything in Java is an object, and each class has a class file. Java objects have an object header, which is the object overview, and one of the pieces of information is the object lock, which is whether or not the object is currently locked, which reference is locked.

Synchronized: Synchronized is a Java keyword. When applied to a method, it means that we lock the method, and if we lock a block of code, it means that we hold the lock within that block of code. Java Effective also advocates reducing the scope of the lock. When we enter the synchronized code block, we lock it, and when we finish, we release the lock.

Deadlock: Colloquially known as a dead lock. If there is no dead lock its declaration cycle is: hold lock -> release lock. After death we can think of it as holding the lock but not releasing the lock, so we didn’t finish synchronizing the block, right? We just need to analyze where the synchronized code block is not executing, and look at the following example. Okay

Demonstrate a deadlock

package com.yang.kuangTeacher; import java.util.concurrent.TimeUnit; /** * @author: Fudy * @date: 2020/9/13 12:21 PM * @decription: Public class DeadLock {public static void main(String[] args) {MarkUp markUp0 = new MarkUp(" dirhiba ",0); MarkUp markUp1 = new MarkUp(" Yang mi ",1); markUp0.start(); markUp1.start(); }} class MarkUp extends Thread {private int choice;}} class MarkUp extends Thread {private int choice; private String userName; private static LipStick lipStick = new LipStick(); private static Mirror mirror = new Mirror(); MarkUp(String userName, int choice) { this.userName = userName; this.choice = choice; } @Override public void run() { try { markUP(); } catch (InterruptedException e) { e.printStackTrace(); }} private void markUP() throws InterruptedException {// If (choice == 0) { Synchronized (lipStick) {system.out.println (userName + "take lipStick "); Timeunit.seconds.sleep (1); / / program execution will stop here -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- here a deadlock -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- > synchronized (mirror) {System. Out. Println (userName + "Got the mirror "); If (choice == 1) {// Synchronize code block lock, Synchronized (mirror) {system.out.println (userName + "get mirror "); synchronized (mirror) {system.out.println (userName +" get mirror "); Timeunit.seconds.sleep (1); / / program execution will stop here -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- here a deadlock -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- > synchronized (lipStick) {System. Out. Println (userName + "Got the lipstick "); } } } } }Copy the code

We have just assumed that a deadlock is caused by a synchronized block of code not being executed, so the lock will not be released. Let’s analyze the causes of the above two deadlock.

  • In Thread 1 mode 0 makeup, sleep for 1 second after we get the lipstick lock (thread 2 May be executed first)

  • In Thread 2 mode 1 makeup since we got the mirror lock, sleep for a second

If thread 1 obtains the lipstick lock first and is ready to take the mirror lock, it finds that the mirror object is held, so it will wait for the mirror lock to be released.

Thread 2 finishes acquiring the mirror lock and is about to take the lipstick lock, but finds that the lipstick object is held, so it will wait for the lipstick lock to be released.

If we don’t close the program, the two threads will wait forever. We can think of it as a deadlock, unable to release the lock.

To solve the deadlock

In the example above, we had deadlocks because we wanted to get two locks to do one thing at a time, but Java Effective advocates reducing the scope of the lock, and we have modified the problem.

We can take the lipstick lock, execute the lipstick method and release the lipstick lock. If we want the mirror lock and then synchronize the code block, we can take the mirror lock.

package com.yang.kuangTeacher; import java.util.concurrent.TimeUnit; /** * @author: Fudy * @date: 2020/9/13 12:21 PM * @decription: Public class DeadLock {public static void main(String[] args) {MarkUp markUp0 = new MarkUp(" dirhiba ",0); MarkUp markUp1 = new MarkUp(" Yang mi ",1); markUp0.start(); markUp1.start(); }} class MarkUp extends Thread {private int choice;}} class MarkUp extends Thread {private int choice; private String userName; private static LipStick lipStick = new LipStick(); private static Mirror mirror = new Mirror(); MarkUp(String userName, int choice) { this.userName = userName; this.choice = choice; } @Override public void run() { try { markUP(); } catch (InterruptedException e) { e.printStackTrace(); }} private void markUP() throws InterruptedException {// If (choice == 0) { Synchronized (lipStick) {system.out.println (userName + "take lipStick "); TimeUnit.SECONDS.sleep(1); } / / get the lipstick and then take the mirror -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- to improve -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- synchronized (mirror) {System. Out. Println (userName + "get the mirror "); If (choice == 1) {synchronized (mirror) {system.out.println (userName + "get the mirror "); TimeUnit.SECONDS.sleep(1); } / / get the mirror with lipStick again after -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- to improve -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- synchronized (lipStick) { System.out.println(userName + "get lipstick "); }}}}Copy the code

By releasing the lock in time, which is to narrow the scope of the synchronized code block, we use releasing the lock in time after the end of the lock, which is a way to solve the deadlock. This example will help us to be aware of the scope of the synchronized code for the lock.