[小白求指点]java线程同步问题

package com.test;

public class TT implements Runnable {
int b = 100;
public synchronized void m1() throws Exception{
b = 1000;
Thread.sleep(5000);
System.out.println("b = " + b);
}
=======================================
public synchronized void m2() throws Exception {
Thread.sleep(2500);
b = 2000;
}

=======================================
public void run() {
    try {
        m1();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) throws Exception {
    TT tt = new TT();
    Thread t = new Thread(tt);
    t.start();
    tt.m2();
}

}
=======================================

小弟认为结果应该是2000,理由:在m1执行后此时b值为1000且休眠5秒,但是m2将b值修改为2000且休眠2.5秒,等到m1的5秒结束后显示b值,此时b值为2000。

但是,系统出来的结果是1000,小弟不理解,请求指点。谢谢!

流程分析:首先主线程执行创建一个套套(tt)对象(注意:此对象只有一把锁),然后再创建一个t线程并开启。
t线程和主线程争抢控制权,假设t线程获得控制权,进入run方法执行m1(注意:m1使用套套的锁),m1使t线程睡眠
5秒(注意:但并未释放套套的锁),在这段时间主线程又获得了控制权,主线程调用m2(注意:m2也是使用synchronized修饰)
方法,但是套套的锁还在m1中使用,主线程就尝试去获取这把锁,所以只有m1执行完释放锁,主线程才能获得这把锁,
才能执行m2方法。去掉m2的synchronized即可获得你想要的结果。手打不易不喜勿喷。

1.b = 100
2.t.start()->1000 sysout
3.tt.m2()->2000 你没输出
尴尬-------

你这个人啊,问题真多。只可言传不可意会,对象只有一个,锁也只有一个。

package com.test;

public class TT implements Runnable {
int b = 100;

public synchronized void m1() throws Exception {
    b = 1000;

    System.out.println("m1执行完毕,b = " + b);
}

public synchronized void m2() throws Exception {
    b = 2000;
    System.out.println("m2执行完毕,最终b值" + b);
}

public void run() {
    try {
        m1();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) throws Exception {
    TT tt = new TT();
    Thread t = new Thread(tt);
    t.start();
    tt.m2();
    tt.m2();
    tt.m2();
}

}

得到的结果如下:
m2执行完毕,最终b值2000
m2执行完毕,最终b值2000
m2执行完毕,最终b值2000
m1执行完毕,b = 1000
(这个结果我运行了很多次都一样)

所以我认为:不应该是在上一个synchronized修饰的方法运行完毕之后再运行下一个synchronized修复的方法。
t.start() 告诉系统它现在准备好了随时可以运行,但在t.start()下还有3个m2要执行,执行完毕3个m2后系统认为有资源可以运行t.start()了,此时t.start()才正式开始运行。
不知道这样理解对不。

真正的问题是其实先执行的是m2而并不是m1,学习多线程的时候一定要注意,并不是写在前面的代码一定先执行,按我这样加几个注释就很清楚了

public class Qquestions_380568 {
    static class TT implements Runnable {
        int b = 100;

        public synchronized void m1() throws Exception {
            System.out.println("---------m1执行,此时m1方法获取锁-----------");
            b = 1000;
            Thread.sleep(5000);
            System.out.println("---------m1执行,此时m1方法释放锁-----------");
            System.out.println("b = " + b);
        }

        public synchronized void m2() throws Exception {
            System.out.println("---------m2执行,此时m2方法获取锁-----------");
            Thread.sleep(2500);
            b = 2000;
            System.out.println("---------m2执行完成,此时m2方法释放锁-----------");
        }

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

    public static void main(String[] args) throws Exception {
        TT tt = new TT();
        Thread t = new Thread(tt);
        t.start();
        tt.m2();
    }
}