• 一道很有意思的java线程题


    这几天看结城浩的《java多线程设计模式》,跟着做一些习题,有几道题目很有意思,记录下自己的体会。

      首先是题目(在原书212页,书尾有解答):

    public class Main {
        public static void main(String[] args) {
            try {
                Blackhole.enter(new Object());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public class Blackhole {    
            public static void enter(Object obj) throws InterruptedException {
            System.out.println("1");
            magic(obj);
            System.out.println("2");
            synchronized (obj) {
                System.out.println("3");
            }
        }
    
        private static void magic(Object obj){}
    }

     代码很简单,要求写出magic()代码,使得输出是

    1
    2

    不能出现3.

    思路:很明显要想不输出3,magic()必须得到obj锁,且不能释放才行。

        private static void magic(final Object obj) throws InterruptedException {
            Thread thread = new Thread() {
                @Override
                public void run() {
                    synchronized (obj) {
                        synchronized (this) {
                            this.setName("LockNow");
                            this.notifyAll();
                        }
                        while (true) {
                        }
                    }
                }
            };
            synchronized (thread) {
                thread.setName("");
                thread.start();
                while (thread.getName().equals("")) {
                    thread.wait();
                }
            }
        }

     作者的思路很巧妙,通过thread.name的值来处理2个线程的执行次序。

       1. 创建一个内部Thread实例thread,先不start()

       2. 然后由主线程获得thread锁,并启动thread线程,然后开始等待。

       3. thread线程会去获得obj锁,获得obj锁之后,该线程会修改自己name,并通知主线程。

       4. 主线程发现条件满足,继续执行

       刚看到答案,有个很大疑问,主线程获得thread锁之后,启动thread线程,而thread线程为了修改name,必须获得自己的锁(否则运行时会报错java.lang.IllegalMonitorStateException),这不死锁了吗?

       仔细一想又不会,因为新线程开启之后,如果新线程运行到synchronized (this)被阻挡而无法修改name,主线程肯定会进入wait,而wait时主线程释放thread锁,新线程就可继续往下跑。

      短短几行代码,线程之间同步协调环环相扣,不得不佩服作者的功力!

  • 相关阅读:
    day14(JavaDoc)
    day15(Java流程控制)
    day12
    day.6
    day10
    day11(运算符)
    day.5
    proc -x cshell fork()
    I/O -x 标准IO fopen-fclose--fgetc-fputc--fgets-fputs--fwrite-fread--fprintf-fscanf
    I/O -x open()-read()-write()-close()-lseek()
  • 原文地址:https://www.cnblogs.com/onlywujun/p/3809311.html
Copyright © 2020-2023  润新知