public class TT implements Runnable {
private int b = 100; public void m1() {
synchronized (this) {
try {
Thread.sleep(3000);
b = 1000;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("b1 = " + b);
}
} public void m2() {
System.out.println("b2 = " + b);
} public void run() {
this.m1();
} public static void main  (String[] args) throws Exception {
TT t = new TT();
Thread t1 = new Thread(t);
t1.start();
Thread.sleep(500);
t.m2();
}
}
输出
b2 = 100
b1 = 1000如果把最后那个Thread.sleep(500)改成5000
那输出
b2 = 1000
b1 = 1000请问下为什么输出不同。m1方法执行过程中
为什么m2方法可以调用b变量啊。
我自己理解。 synchronized锁定后。其中的代码都锁定了。
谢谢

解决方案 »

  1.   

      public void m2() {
            System.out.println("b2 = " + b);
        }
    改成
      public synchronized void m2() {
            System.out.println("b2 = " + b);
        }
    这样才保证两个方法在同一对象上的同步
      

  2.   

    1, m1()中有 sleep(3000) 3000>500, 所以先是执行t.m2(),再执行t.m1() 
    2, 而把sleep(500)改为sleep(5000)后,执行的顺序就要反过来了,m1()中的变量b被修改了,所以两个输入都是1000
    3, m2()是TT类中的成员方法,当然可以调用本类中的变量b
    4,代码中的synchronized关键字表示改代码块被加锁,在这段代码执行过程中变量b的值外部是不能修改的
      

  3.   


    不好意思理解能力有限
    3中说明可以调用本类中的变量b
    那此时锁定代码块里面b改变了 m2方法可以用调用?可是4中说道 在这段代码执行过程中变量b的值外部是不能修改的 
    请问怎么理解。
      

  4.   


    首先,代码中的变量b是共享变量,m1()和m2()中被称为临界区代码。
    Java的对象锁机制规定了被synchronized关键字锁住的代码块和方法,每次只允许一个线程访问其中的共享变量
    而你的代码中只有两个线程,主线程和t1,当执行t1.start()方法是,该线程运行,调用run()方法,run()方法再调用m1(),而m1()你让线程t1休眠了3000毫秒,t1让出来对象锁,所以这时执行主线程,调用m2(),打印b
    而如果让住线程休眠5000毫秒,这时线程t1将先被唤醒,将b修改为1000,然后再执行主线程,最后输入b的结果都是1000
      

  5.   

    Java的对象锁机制规定了被synchronized关键字锁住的代码块和方法,每次只允许一个线程访问其中的共享变量
    而你的代码中只有两个线程,主线程和t1,当执行t1.start()方法是,该线程运行,调用run()方法,run()方法再调用m1(),而m1()你让线程t1休眠了3000毫秒,t1让出来对象锁,所以这时执行主线程,调用m2(),打印b
    而如果让住线程休眠5000毫秒,这时线程t1将先被唤醒,将b修改为1000,然后再执行主线程,最后输入b的结果都是1000
      

  6.   

    个人觉得.m1()中的synchronized锁定的代码块.必须是在sleep(3000)后才会给变量b加上锁.要想看到锁定b的效果.可以将m1()中的代码修改.
    synchronized (this) {
                try {
                    b = 1000;
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("b1 = " + b);
            }
    这样就无论怎么样都是先.执行完该代码块,包括b变量的使用.
      

  7.   

    因为m2()方法没有同步,只有同步代码块之间存在互斥,同步的和非同步的之间不互斥
    public synchronized void m2() {//把m2也同步了
            System.out.println("b2 = " + b);
        }
      

  8.   

    起码我认为你说的 而m1()你让线程t1休眠了3000毫秒,t1让出来对象锁,所以这时执行主线程
    这句话不对,对象锁定状态。sleep是不会跳出对象锁的。我比较认可 synchronized锁定的变量其他的非同步方法依然可以访问 这种说法