简体   繁体   中英

a few questions about thread synchronization

class Q {
int n;
boolean sse = false;
synchronized int get(){
    while (!sse)
        try{
            wait();
        }catch(InterruptedException e){
            System.out.println("Interrupted Exception Caught");
        }
    System.out.println("Got :" + n);
    sse = false;
    notify();
    return n;
        }
synchronized void put(int n){
    while(sse)
        try{
            wait();
        }catch(InterruptedException e){
         System.out.println("Caught");
        }
    this.n = n;
    sse = true;
    System.out.println("Put :" + n);
    notify();
}

}
class Producer implements Runnable{
    Q q;
    Producer(Q q) {
        this.q = q;
        new Thread(this, "Prodcuer").start();
    }
    public void run(){
        int i = 0;
        while(true) {
        q.put(i++);
        }
    }
}
class Consumer implements Runnable{
    Q q;
    Consumer(Q q) {
        this.q = q;
        new Thread(this, "Consumer").start();
    }
    public void run(){

        while(true) {
        q.get();
        }
    }
}
public class Main {


    public static void main(String[] args) {
  Q q = new Q();
  new Producer(q);
  new Consumer(q);
  System.out.println("Press Control C to stop");
    }

}

I have 2 questions.

Q1. now the definition of wait() function is like this : tells the calling thread to give up monitor and go to sleep until some other thread enters the same monitor and calls notify(). Now in this program two threads(One related to consumer and one to producer) use the same object q in get and put respectively. So is there only one monitor existing for the object q, which is entered when any thread uses a function involving q?

Q2 Here the Consumer waits until Producer notifies it, but the Producer also waits until the consumer notifies it? Who starts first? In the output, Producer comes first but how?

  1. Q has just one monitor
  2. Producer starts first because you called its constructor first in your Main.

About the second question: When your program starts, the Q object "is empty", which means there is no object that the consumer could get. Thus the consumer has to wait until the producer puts something in. This means the producer will first print its "Put", then the consumer can retrieve it and print its "Get".

On the other hand, if the producer tries to put something again before the consumer had taken the previous element out of the queue, the producer has to wait until it is taken.

This means you will get alternating "Put" and "Get" output (assuming the output stream does not do some reordering).

This differs a bit from SynchronousQueue in that here the producer can proceed if the queue was empty before (and the consumer can proceed if it was full before), while for SynchronousQueue it would wait until the consumer is ready to take it (which means put and get are always overlapping in time, and can't be called on the same thread).

Your queue is more similar to an ArrayBlockingQueue with capacity 1.

  1. Each object (instance) in jvm has exactly one monitor. This is crucial for achieving the intended behavior (ie ensuring that only one thread from a bunch of threads goes ahead while others wait).

    You can visualize the lock as a kind of token/pass that is needed for entering a room. Many hospitals employ such a scheme to ensure that only a single attendant can be with a particular patient. If you want to take place of current attendant, you should wait() for the current attendant to come out and hand over the pass to you. Only then you can go pass the security to enter the restricted area. Off course this scheme only works if there is only one token/pass per patient. Otherwise it will be impossible for the security personnel to know which patient already have an attendant.

  2. With your code, the producer thread will start first because you are creating the producer before the consumer. But if you want to know which one of the get() or put() be called first then there is no guarantee of the order. In practice you will usually see the put() being called first because the producer thread was started first. But theoretically there remains possibility of seeing the get() called first. This is possible because thread scheduler might switch out the producer thread before it reaches the put() call.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM