【Java高级】从一个小例子说明Java的synchronized、wait()和notify()机制

本文为原创文章,转载请注明出处
查看[Java]系列内容请点击:https://www.jianshu.com/nb/45938443

如果你不知道Java的重入锁等请参考:https://www.jianshu.com/p/ed96690edb86

在Java中synchronized关键字用来控制同步,我们知道,synchronized控制一段同步代码块的时候,需要在里面传入一个对象,JVM就会使用这个对象内置的锁机制来实现互斥锁,看如下代码,多线程顺序执行代码块:

public class Main {
    private static Object lock = new Object();

    public static void main(String[] args) throws Exception {

        new Thread(new MyRunnable()).start();
        new Thread(new MyRunnable()).start();
        new Thread(new MyRunnable()).start();
    }

    private static class MyRunnable implements Runnable {

        @Override
        public void run() {
            try {
                synchronized (lock) { // 这里保证只有一个线程能进入
                    System.out.println("线程:" + Thread.currentThread().getId());
                    Thread.sleep(500);
                    System.out.println("线程:" + Thread.currentThread().getId());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

可以看到,虽然我们在不同的线程内都等待了一段时间,但是仍然是顺序执行的,执行结果:

线程:14
线程:14
线程:16
线程:16
线程:15
线程:15

那么,如何使得不按照顺序打印呢?

我们调整一下程序,使用waitnotify操作来进行:

public class Main {
    private static Object lock = new Object();
    private static int count = 3;

    public static void main(String[] args) throws Exception {

        new Thread(new MyRunnable()).start();
        new Thread(new MyRunnable()).start();
        new Thread(new MyRunnable()).start();
    }

    private static class MyRunnable implements Runnable {

        @Override
        public void run() {
            try {
                synchronized (lock) {
                    System.out.println("线程:" + Thread.currentThread().getId());

                    count--;
                    if (count > 0) lock.wait();
                    Thread.sleep(500);
                    System.out.println("线程:" + Thread.currentThread().getId());
                    lock.notify();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果:

线程:14
线程:16
线程:15
线程:15
线程:14
线程:16

可以看到,我们在synchronized的内部调用了wait使得当前线程休眠并且释放持有的锁,使得其他线程能进入synchronized代码块执行。休眠的线程进入lock对象的内部监视器等待队列等待执行。然后在lock.notify()处唤醒这些代码继续竞争lock锁并执行后续内容。

你可能感兴趣的:(【Java高级】从一个小例子说明Java的synchronized、wait()和notify()机制)