线程执行顺序问题(Synchronized、自旋锁)

来源:14-10 ThreadMXBean工具介绍

superLiuLiuLiu

2019-11-22

悟空老师,我在做一道面试题遇到一个想不通的地方面试题如下:

public class TestSync2 implements Runnable {
    int b = 100;

    synchronized void m1() throws InterruptedException {
        b = 1000;
        Thread.sleep(500); //6
        System.out.println("b=" + b);
    }

    synchronized void m2() throws InterruptedException {
        Thread.sleep(250); //5
        b = 2000;
    }

    public static void main(String[] args) throws InterruptedException {
        TestSync2 tt = new TestSync2();
        Thread t = new Thread(tt);  //1
        t.start(); //2

        tt.m2(); //3
        System.out.println("main thread b=" + tt.b); //4
    }

    @Override
    public void run() {
        try {
            m1();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

这个程序的执行结果为什么会有:
main thread b=1000
b=1000
这种情况呢?
我先说一下我的理解,这道题主要是因为主线程和t线程开始执行顺序不同引起的结果不同,我假设主线程先执行,然后抢到了锁对象(this对象),然后线程睡眠250ms,此时t线程执行m1方法,因为锁对象已经被抢占,故自旋等待主线程释放锁对象,主线程执行完m2方法并释放锁对象,此时b=2000,那么为什么会出现上面main thread b = 1000的结果呢?

希望老师可以解惑。

写回答

1回答

悟空

2019-11-22

因为还没打印之前,m1就运行并修改了b,m1的速度比打印快,如果你在m1里的一开始加一句休眠5毫秒,,那结果就是2000,我刚才试过了。

2
8
悟空
回复
大唐雨夜
会改为1000的,但是打印速度不能太快,你把休眠的时间从500和250ms改成5000和2500ms就懂了
2020-03-05
共8条回复

线程八大核心+Java并发原理及企业级并发解决方案

完整的并发知识网络+丰富的工作内容分享+50余道并发高频面试题

2512 学习 · 939 问题

查看课程