美文网首页
线程同步之wait/notify

线程同步之wait/notify

作者: RookieRun | 来源:发表于2020-11-16 15:05 被阅读0次

    一直对线程同步的wait/notify不太理解, 今天有空demo实践了下

    public class Test {
        private static final Object lock = new Object();
    
        public static void main(String[] args) {
            testWaitAndNotify();
        }
    
        private static void testWaitAndNotify() {
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (lock) {
                        while (true) {
                            System.out.println("thread1 的run 方法-准备睡两秒->" + System.currentTimeMillis());
                            try {
                                Thread.sleep(2000);
                                System.out.println("thread1 -醒了释放锁了-自己wait->" + System.currentTimeMillis());(1)
                                lock.notify();
                                System.out.println("thread1 -我在睡3秒后才会释放锁->" + System.currentTimeMillis());
                                Thread.sleep(3000);
                                lock.wait();(1)
                                System.out.println("thread1 被叫醒了-->" + System.currentTimeMillis());
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            });
            thread1.start();
            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (lock) {
                        while (true) {
                            System.out.println("thread2 的run 方法-->准备睡两秒->" + System.currentTimeMillis());
                            try {
                                Thread.sleep(2000);
    //                            lock.wait();
                                System.out.println("thread2醒了释放锁了-自己wait-->" + System.currentTimeMillis());
                                lock.notify();
                                System.out.println("thread2 -我在睡3秒后才会释放锁->" + System.currentTimeMillis());
                                Thread.sleep(3000);
                                lock.wait();(2)
                                System.out.println("thread2 被叫醒了-->" + System.currentTimeMillis());
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            });
            thread2.start();
    
        }
    }
    
    image.png

    可以看到,thread1先拿到锁并得到执行,然后在(1)处执行wait让出锁,然后,thread2拿到锁,并得到执行,并在(2)处执行wait释放锁,然后需要注意的是,本线程是在notify所在代码块执行完毕后,才有机会竞争该把锁

     /**
         * Causes the current thread to wait until another thread invokes the
         * {@link java.lang.Object#notify()} method or the
         * {@link java.lang.Object#notifyAll()} method for this object.
         * In other words, this method behaves exactly as if it simply
         * performs the call {@code wait(0)}.
         * <p>
         * The current thread must own this object's monitor. The thread
         * releases ownership of this monitor and waits until another thread
         * notifies threads waiting on this object's monitor to wake up
         * either through a call to the {@code notify} method or the
         * {@code notifyAll} method. The thread then waits until it can
         * re-obtain ownership of the monitor and resumes execution.
         * <p>
         * As in the one argument version, interrupts and spurious wakeups are
         * possible, and this method should always be used in a loop:
         * <pre>
         *     synchronized (obj) {
         *         while (&lt;condition does not hold&gt;)
         *             obj.wait();
         *         ... // Perform action appropriate to condition
         *     }
         * </pre>
         * This method should only be called by a thread that is the owner
         * of this object's monitor. See the {@code notify} method for a
         * description of the ways in which a thread can become the owner of
         * a monitor.
         *
         * @throws  IllegalMonitorStateException  if the current thread is not
         *               the owner of the object's monitor.
         * @throws  InterruptedException if any thread interrupted the
         *             current thread before or while the current thread
         *             was waiting for a notification.  The <i>interrupted
         *             status</i> of the current thread is cleared when
         *             this exception is thrown.
         * @see        java.lang.Object#notify()
         * @see        java.lang.Object#notifyAll()
         */
        @FastNative
        public final native void wait() throws InterruptedException;
    
     /**
         * Wakes up a single thread that is waiting on this object's
         * monitor. If any threads are waiting on this object, one of them
         * is chosen to be awakened. The choice is arbitrary and occurs at
         * the discretion of the implementation. A thread waits on an object's
         * monitor by calling one of the {@code wait} methods.
         * <p>
         * The awakened thread will not be able to proceed until the current
         * thread relinquishes the lock on this object. The awakened thread will
         * compete in the usual manner with any other threads that might be
         * actively competing to synchronize on this object; for example, the
         * awakened thread enjoys no reliable privilege or disadvantage in being
         * the next thread to lock this object.
         * <p>
         * This method should only be called by a thread that is the owner
         * of this object's monitor. A thread becomes the owner of the
         * object's monitor in one of three ways:
         * <ul>
         * <li>By executing a synchronized instance method of that object.
         * <li>By executing the body of a {@code synchronized} statement
         *     that synchronizes on the object.
         * <li>For objects of type {@code Class,} by executing a
         *     synchronized static method of that class.
         * </ul>
         * <p>
         * Only one thread at a time can own an object's monitor.
         *
         * @throws  IllegalMonitorStateException  if the current thread is not
         *               the owner of this object's monitor.
         * @see        java.lang.Object#notifyAll()
         * @see        java.lang.Object#wait()
         */
        @FastNative
        public final native void notify();
    
        /**
         * Wakes up all threads that are waiting on this object's monitor. A
         * thread waits on an object's monitor by calling one of the
         * {@code wait} methods.
         * <p>
         * The awakened threads will not be able to proceed until the current
         * thread relinquishes the lock on this object. The awakened threads
         * will compete in the usual manner with any other threads that might
         * be actively competing to synchronize on this object; for example,
         * the awakened threads enjoy no reliable privilege or disadvantage in
         * being the next thread to lock this object.
         * <p>
         * This method should only be called by a thread that is the owner
         * of this object's monitor. See the {@code notify} method for a
         * description of the ways in which a thread can become the owner of
         * a monitor.
         *
         * @throws  IllegalMonitorStateException  if the current thread is not
         *               the owner of this object's monitor.
         * @see        java.lang.Object#notify()
         * @see        java.lang.Object#wait()
         */
        @FastNative
        public final native void notifyAll();
    

    (1).wait(),notify(),notifyAll()都是本地方法,并且为final方法,无法被重写
    (2).wait(),notify(),notifyAll(),是object的方法,不是Thread的方法
    (3).调用某个对象的wait()的方法能让当前线程阻塞,并且,当前线程必须拥有此对象的monitor
    (4).调用某个对象的notify()方法能够唤醒一个正在等待这个对象monitor的线程,度过由多个线程在等待这个monitor,则只能唤醒其中一个(按等待顺序)
    (5).调用notifyAll()能狗焕醒所有正在等待这个对象的monitor的线程

    相关文章

      网友评论

          本文标题:线程同步之wait/notify

          本文链接:https://www.haomeiwen.com/subject/ofxzbktx.html