Producer-consumer issues in multithreading

Producer-consumer issues in multithreading

Thread Security Issues

In multithreaded programming, it is common for multiple threads to operate on the same resource at the same time, resulting in thread insecurity, which can be solved by queue locking.
Using the synchronized keyword, a method or a block of code can be locked, and only after the locked thread is executed can other threads operate, thereby resolving the problem of thread synchronization and greatly enhancing thread security.

Issues raised by producers and consumers

However, in many cases, synchronization between threads is not enough, and messaging communication between different threads is also required. Therefore, producer-consumer issues are raised.

Question raised:
For producers, consumers need to be notified to wait before they produce products, and consumers need to be notified to consume when they are finished.
For consumers, they need to notify the producer to produce the product after they have consumed it, and they need to wait when the product is empty.

When we look at producers and consumers as two threads, communication between threads is needed to solve the above problem.

Methods to be used in producer-consumer problems

Method Name Method Description
wait() Keep the thread waiting and release the lock until other threads notify it
wait(long timeout) Specify the number of milliseconds to wait
notify() Wake up a waiting thread
notifyAll() Wake up all threads on the same object that call the wait() method, with the higher priority thread scheduling first

Solutions to producer-consumer problems

  • Pipeline method
    Create a buffer where producers and consumers allocate resources.
public class TestPC {
    public static void main(String[] args) {
        SynContainer synContainer = new SynContainer();
        new Productor(synContainer).start();
        new Consumer(synContainer).start();
    }
}
//Producer
class Productor extends Thread{
    SynContainer synContainer;
    public Productor(SynContainer synContainer){
        this.synContainer = synContainer;
    }
    @Override
    public void run() {
        for (int i = 1; i < 100; i++) {
            synContainer.push(new Chicken(i));
            System.out.println("Produced"+i+"Chicken");
        }
    }
}
//Consumer
class Consumer extends Thread{
    SynContainer synContainer;
    public Consumer(SynContainer synContainer){
        this.synContainer = synContainer;
    }
    @Override
    public void run() {
        for (int i = 1; i < 100; i++) {
            System.out.println("Consumed"+synContainer.pop().id+"Chicken");
        }
    }
}
//Product (KFC)
class Chicken{
    int id;
    public Chicken(int id){
        this.id = id;
    }
}
//Buffer
class SynContainer{
    //container
    Chicken[] chickens = new Chicken[10];
    //Container Counter
    int count = 0;
    //Producer produces products in containers
    public synchronized void push(Chicken chicken){
        //Determine if the buffer is full and, if so, notify consumers of their consumption
        if(count == chickens.length){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        chickens[count] = chicken;
        count++;

        this.notify();
    }
    //Consumers remove products from containers
    public synchronized Chicken pop(){
        //Determine if the buffer is empty.Notify producer of production if empty
        if(count == 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count--;
        Chicken chicken = chickens[count];
        this.notify();
        return chicken;
    }
}
  • Semaphore method
    Use a semaphore flag to make a thread wait or wake up.
public class TestPC {
    public static void main(String[] args) {
        TV tv = new TV();
        new Player(tv).start();
        new Watcher(tv).start();
    }
}
//Producer (Actor)
class Player extends Thread{
    TV tv;
    public Player(TV tv){
        this.tv = tv;
    }
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            tv.play("Java");
        }
    }
}
//Consumer (audience)
class Watcher extends Thread{
    TV tv;
    public Watcher(TV tv){
        this.tv = tv;
    }
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            tv.watch();
        }
    }
}
//Products (Programs)
class TV{
    String voice;           //program
    boolean flag = true;    //Is there a program
    //Performer Performance
    public synchronized void play(String voice){
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("The actors performed:"+voice);
        this.notifyAll();
        this.voice = voice;
        this.flag = !this.flag;
    }
    //Audience Watch
    public synchronized void watch(){
        if(flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notifyAll();
        System.out.println("The audience watched:"+voice);
        this.flag = !this.flag;
    }
}
10 original articles published. 2. 120 visits
Private letter follow

Tags: Programming Java

Posted on Fri, 13 Mar 2020 22:19:13 -0400 by gite_ashish