美文网首页
【Java高级】从一个小例子说明Java的synchronize

【Java高级】从一个小例子说明Java的synchronize

作者: 大栗几 | 来源:发表于2020-07-01 22:53 被阅读0次

    本文为原创文章,转载请注明出处
    查看[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的synchronize

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