Junior JUC

Article directory

The basic theory needed in this paper

Multi thread programming exercise (4)

Corresponding to the previous note, this chapter practices a new writing method of producer consumer model.
This time, ReentrantLock(), newCondition() are introduced to cancel the use of synchronized keyword;
Correspondingly, the synchronized wait(), notify(), and notifyAll() methods also correspond to the condition.await(), condition.signal(), and condition.signalAll() methods.
The condition object needs to be created through the lock object.
The following is an override of the resource class AirCondition class. See code block for details:

class AirConditioner{
   private int number = 0;
   private Lock lock = new ReentrantLock();
   private Condition condition = lock.newCondition();
   public void increment(){
        lock.lock();
        try
        {
            //Real business logic is only written in try
            //1. judgement
            while (number != 0){
                condition.await();//this.wait();
            }
            //2. work
            number++;
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            //3. notice
            condition.signalAll();//this.notifyAll();
        } catch (Exception e) {
             e.printStackTrace();
        } finally {
            lock.unlock();
        }
   }
}

Why introduce the above new API for use?
The condition.await(), condition.signal(), condition.signalAll() methods must have their own advantages.
For a fixed thread order request, there will be no competitive scheduling between threads if only one thread is awakened. That is to say, the so-called "point strike, precise delivery" has been realized.
The previous notifyAll() method only wakes up all threads waiting to get control of the object.
Lock lock is usually used with condition to realize sequential access of threads. Such sequential access is a common thing in e-commerce projects: "placing an order, deducting inventory and adjusting payment".
If you look at the following topic, you may have a further understanding of this thread's "precise notification, sequential access".
Title:
Multiple threads are started in order to realize the starting order of a - > b - > C. The three thread startup requirements are as follows:
AA printing 5 times, BB printing 10 times, CC printing 5 times, AA printing 5 times, BB printing 10 times, CC printing 5 times Repeat for 10 rounds.

class ShareResource{
    private int number = 1; //1:A 2:B 3:C
    private Lock lock = new ReentrantLock();
    //One lock with three keys
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    public void print5(){
        lock.lock();
        try
        {
            //1. judgement
            while(number != 1){
                condition1.await();
            }

            //2. work
            for (int i = 1; i <= 5; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }

            //3. notice
            //Flag bit modification
            number = 2;
            //Wake up a specific thread, not all
            condition2.signal();

        } catch (Exception e) {
             e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print10(){
        lock.lock();
        try
        {
            while(number != 2){
                condition2.await();
            }
            for (int i = 1; i <= 10; i++) {
                System.out.println(Thread.currentThread().getName()+"\t"+i);
            }
            //Flag bit modification
            number = 3;
            condition3.signal();
        } catch (Exception e) {
             e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print15(){
        lock.lock();
        try
        {
            while(number != 3){
                condition3.await();
            }
            for (int i = 1; i <= 15; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            //Flag bit modification
            number = 1;
            condition1.signal();
        } catch (Exception e) {
             e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
public class ThreadOrderAccess {
    public static void main(String[] args) {
        ShareResource shareResource = new ShareResource();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                shareResource.print5();
            }
        },"A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                shareResource.print10();
            }
        },"B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                shareResource.print15();
            }
        },"C").start();
    }
}

All in all, lock is used in conjunction with condition to precisely wake up a specific thread and execute it.

Published 2 original articles, won praise 0, visited 32
Private letter follow

Tags: Programming

Posted on Tue, 10 Mar 2020 00:13:55 -0700 by dcole