Does notify/notifyall release the lock being held

前端 未结 8 1457
忘掉有多难
忘掉有多难 2020-12-09 02:41

I am confused a bit about wait and notify/notifyAll.

I know there is a lock for every java object. I know wait will release the lock for other thread. How about noti

8条回答
  •  渐次进展
    2020-12-09 02:50

    To clarify my understanding and to provide an example for all to show when the lock is released, I have added print statements to the following code after the call to notify()/NotifyAll():

    class ThreadDemo {
        public static void main(String[] args) {
            Shared s = new Shared();
            new Producer(s).start();
            new Consumer(s).start();
        }
    }
    
    class Shared {
        private char c = '\u0000';
        private boolean writeable = true;
    
        synchronized void setSharedChar(char c) {
            while (!writeable)
                try {
                    wait();
                } catch (InterruptedException e) {
                }
    
            this.c = c;
            writeable = false;
            notifyAll();
            System.out.println("setSharedChar notify() called - still in synchronized block.");
        }
    
        synchronized char getSharedChar() {
            while (writeable)
                try {
                    wait();
                } catch (InterruptedException e) {
                }
    
            writeable = true;
            notifyAll();
            System.out.println("getSharedChar notify() called - still in synchronized block.");
    
            return c;
        }
    }
    
    class Producer extends Thread {
        private Shared s;
    
        Producer(Shared s) {
            this.s = s;
        }
    
        public void run() {
            System.out.println("Starting producer thread.");
            for (char ch = 'A'; ch <= 'Z'; ch++) {
                System.out.println("Producer thread getting ready to create a char.");
                try {
                    Thread.sleep((int) (Math.random() * 1000));
                } catch (InterruptedException e) {
                }
    
                s.setSharedChar(ch);
                System.out.println(ch + " produced by producer.");
            }
        }
    }
    
    class Consumer extends Thread {
        private Shared s;
    
        Consumer(Shared s) {
            this.s = s;
        }
    
        public void run() {
            System.out.println("Starting consumer thread.");
            char ch;
    
            do {
                System.out.println("Consumer thread getting ready to read a char.");
                try {
                    Thread.sleep((int) (Math.random() * 1000));
                } catch (InterruptedException e) {
                }
    
                ch = s.getSharedChar();
                System.out.println(ch + " consumed by consumer.");
            } while (ch != 'Z');
        }
    }
    

    When I ran this example enough times, there was a point where I did eventually see the output of the program show:

    ...
    F produced by producer.
    Producer thread getting ready to create a char.
    getSharedChar notify() called - still in synchronized block.
    F consumed by consumer.
    Consumer thread getting ready to read a char.
    setSharedChar notify() called - still in synchronized block.
    G produced by producer.
    Producer thread getting ready to create a char.
    getSharedChar notify() called - still in synchronized block.
    setSharedChar notify() called - still in synchronized block.
    G consumed by consumer.
    

    Since the output getSharedChar is able to appear before setSharedChar, it appears that the lock is being released immediately or not required to reenter the synchronized getSharedChar() function by the call to notifyAll(). The lock may still be in place, but if you can reenter the function without it, what is the difference? I was able to see similar output substituting notify() for notifyAll(). This was done on Java 1.7.0_15 on a 64 bit Windows 7 system.

提交回复
热议问题