Fourth article on concurrent programming

Keywords: Java Programming Lombok

Fourth article on concurrent programming

 

4.11 More locks

A large house has two functions: sleeping, learning and being irrelevant.
Now Xiao Nan has to learn and the little girl has to sleep, but if she only uses one room (one object lock), the concurrency is very low.
Prepare multiple rooms (multiple object locks) for solution

4.12 Activeness

deadlock
When a thread needs to acquire multiple locks at the same time, deadlocks can easily occur.
The t1 thread acquires the A object lock, and then wants to acquire the B object lock
The t2 thread acquires the B object lock, and then wants to acquire the A object lock

Locate Deadlock

  • To detect deadlocks, you can use the jconsole tool or use jps to locate the process id and jstack to locate the deadlock:

hunger

Let's start with an example of thread hunger, using sequential locking to solve previous deadlocks

Sequential Locking Solution

4.13 ReentrantLock

It has the following characteristics relative to synchronized

  • Interruptable
  • Timeout can be set
  • Can be set to fair lock
  • Supports multiple conditional variables
    Like synch, reentrant is supported
    Reentrant
    Reentrant refers to the use of a thread that, if it acquires the lock for the first time, has the right to acquire it again because it is the owner of the lock
    If the lock is not reentrant, the second time the lock is acquired, the lock itself will be blocked
    Basic Grammar

Sequence control of synchronization mode

Fixed run order
For example, you must print 2 and 1 first
wait notify version

Alternate Output

Thread 1 outputs a5 times, thread 2 outputs b5 times, and thread 3 outputs c5 times.Now I want to output how abcabcabcabcabc is implemented

package com.example.demo;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Test27 {
    public static void main(String[] args) {
        WaitNotify waitNotify = new WaitNotify(1, 5);
        new Thread(() -> {
            waitNotify.print("a", 1, 2);
        }).start();
        new Thread(() -> {
            waitNotify.print("b", 2, 3);
        }).start();
        new Thread(() -> {
            waitNotify.print("c", 3, 1);
        }).start();
    }
}

/**
 * Output waiting for tag next tag
 * a                1               2
 * b                2               3
 * c                3               1
 */
class WaitNotify {

    /**
     * Print
     * @param str
     * @param waitFlag
     * @param nextFLag
     */
    public void print(String str, int waitFlag, int nextFLag) {
        for (int i = 0; i < loopNumber; i++) {
            synchronized (this) {
                while (flag != waitFlag) {
                    try {
                        this.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(str);
                flag = nextFLag;
                this.notifyAll();
            }
        }
    }

    /**
     * Wait tag
     */
    private int flag;

    /**
     * Number of loops
     */
    private int loopNumber;

    public WaitNotify(int flag, int loopNumber) {
        this.flag = flag;
        this.loopNumber = loopNumber;
    }
}
package com.example.demo;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Test2 {
    public static void main(String[] args) throws InterruptedException {
        AwaitSignal awaitSignal = new AwaitSignal(5);
        Condition a = awaitSignal.newCondition();
        Condition b = awaitSignal.newCondition();
        Condition c = awaitSignal.newCondition();
        new Thread(() -> {
            awaitSignal.print("a", a, b);
        }).start();
        new Thread(() -> {
            awaitSignal.print("b", b, c);
        }).start();
        new Thread(() -> {
            awaitSignal.print("c", c, a);
        }).start();

        Thread.sleep(1000);
        awaitSignal.lock();
        try {
            System.out.println("Start...");
            a.signal();
        } finally {
            awaitSignal.unlock();
        }
    }
}

class AwaitSignal extends ReentrantLock {
    private int loopNumber;

    public AwaitSignal(int loopNumber) {
        this.loopNumber = loopNumber;
    }

    /**
     * Parameter 1 prints, parameter 2 enters that lounge, parameter 3 next Lounge
     * @param str
     * @param current
     * @param next
     */
    public void print(String str, Condition current, Condition next) {
        for (int i = 0; i < loopNumber; i++) {
            lock();
            try {
                current.await();
                System.out.println(str);
                next.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                unlock();
            }
        }
    }

}

Posted by greencoin on Fri, 14 Feb 2020 18:56:44 -0800