public class TT implements Runnable {
int b = 100;
public synchronized void m1() throws Exception{
//Thread.sleep(2000);
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();
System.out.println(tt.b);
}
}
int b = 100;
public synchronized void m1() throws Exception{
//Thread.sleep(2000);
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();
System.out.println(tt.b);
}
}
1000
b = 1000
当我设立了一个断点后的执行结果为:
b = 1000
2000
为什么会是这个样子的呀?请教各位高手啊!
断点监视启动了另一个线程,而且不止一个!
一个是你创建的线程
一个是当前的主线程
如果你在主线程里边设置断点当前的主线程当然不会再执行,你创建的线程会继续执行。
在这里应该实现了你的同步,因为你创建了一个对象tt,调用的也是同步方法。
只不过:
tt.m2();
执行完毕的时候释放了对象锁,你新创建的线程得以执行
赋值表1000
然后又执行
System.out.println(tt.b);
最后又输出
System.out.println("b = " + b);
结果竟然是 b = = 2000
2000
b = 1000
谈一下我的个人理解:
首先,主函数中的System.out.println()方法,显示的内容tt.b是没有同步锁的。
其次,解释第一种现象。
1.主函数运行t.start()方法,会让创建的线程进入runnable状态,等到t获得CPU时间片时运行run方法。
但是,t还没有获得CPU的时间片,因为,CPU在被主线程执行,且主线程的时间片还没有被用完。
2.调用tt.m2()方法,主线程sleep(2500);
3.由于主线程sleep,t线程获得运行机会,调用m1();方法,但是由于m1是线程同步的,所以,t线程被同步阻塞。
4.主线程sleep结束,将tt.b赋值为2000 。tt.m2();方法结束。(互斥锁被释放)
5.t线程由于互斥资源被释放,进而执行m1中的代码。将tt.b赋值为1000 。
6.主线程执行System.out.println(tt.b);方法。
7.t线程进行sleep,继续后面的代码。
问题的关键是,5和6的执行顺序,并不是固定的。有可能先进行6然后才是5,多线程并发嘛,要根据操作系统的当前状况而定。
但是,楼主的系统,可能是先5后6 吧。
第三,解释第二种现象。
1.设置断点的情况下,被设置断点的线程会在断点进行挂起。
2.主函数运行t.start()方法后,会让创建的线程进入runnable状态,由于主线程被断点挂起,所以,t会得到CPU的时间片而执行run方法。
3.然后调用t.m1()方法。(这是即使手快,让断点在m1的sleep结束前,主线程就执行到tt.m2()方法,也不行,因为tt.m1()是线程同步的,
并且,还没有执行完毕,这时,你会发现程序会等一会,才执行tt.m2()。)
4.主线程调用tt.m2()方法。
5.断点调试的结果,一般都是不会变化的,因为,人的反映还是没有计算机快的。
呵呵。
main线程中调用System.out.println(tt.b)是不用等待m1方法结束才运行的。在同一类实例中,所有被synchronized修饰的方法才需要等待同步锁。