黑马程序员技术交流社区
标题:
synchronization同步运行结果分析?
[打印本页]
作者:
刘文超
时间:
2013-1-2 17:02
标题:
synchronization同步运行结果分析?
为什么
结果
为:
2000
a =1000
b = 1000
竟然不是m1()先执行完、打印,而是主线程抢了先??
package org.qyx.online;
public class TestSynchro implements Runnable {
int b = 100;
public synchronized void m1() throws Exception {
b = 1000;
Thread.sleep(1000);
System.out.println("b = " + b);
}
public synchronized void m2() throws Exception {
Thread.sleep(2500);
b = 2000;
System.out.println(b);
}
public void run() {
try {
m1();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
TestSynchro tt = new TestSynchro();
Thread t = new Thread(tt);
t.start();
tt.m2();
System.out.println("a =" + tt.b);
}
}
复制代码
作者:
王少雷
时间:
2013-1-2 18:32
Thread t = new Thread(tt);
t.start();
这时候抢到线程,有可能没执行权,执行权在主函数里。
tt.m2();
// 这里又调用 了方法 b=2000
//线程抢到执行权又运行了run方法 tt.b =1000
System.out.println("a =" + tt.b);
//随后线程又休息 最后被唤醒后 又来一个 b=1000
结果故为:
2000
a =1000
b = 1000
作者:
黑马王振宇
时间:
2013-1-2 19:17
本帖最后由 小律队员 于 2013-1-2 19:35 编辑
这里涉及到线程同步问题,说白了就是主线程和t两个线程同时执行,
两个都有锁,所以说白了就是看操作系统把cpu先给谁,运行过程如下:main开始,t.start()后,实际调用的是run方法,也就是m1()方法,线程同步,主线程继续,然后同时tt.m2()也被调用,看操作系统先给谁cpu(就是谁先得到cpu处理,cpu时间片)
如果m1先得到cpu,那么先执行完m1这个方法才能继续,(因为有锁)(可以理解为tt.m2()等着这把锁才能执行),结果是b被赋值1000,等1秒然后输出b = 1000,然后m2执行,等2.5秒,输出2000,再然后输出a = 2000。
如果m2先得到cpu,那么就是你这种结果了,先等2.5秒,然后输出2000,然后这时候m1拿到锁,和main(也就是m2以后的语句)一起执行,这时候b值被赋予1000,然后m1等1秒的过程中,main先打印a = 1000,然后m1再打印 b = 1000。
下面是我以前写的代码,之后总结出来的结论,和你的程序挺相似,只是为了扩大效果sleep时间有点长,其他还好。
无标题-2.jpg
(142 KB, 下载次数: 47)
下载附件
2013-1-2 19:35 上传
作者:
冉世友
时间:
2013-1-2 23:26
上面的的分析都很正确,是因为线程之间抢夺执行权导致的
我运行了下,还出现过这个结果:
2000
a =2000
b = 1000
要指定子线程和主线程哪个先运行的话,可以定义一个标记
作者:
何竹冬
时间:
2013-1-3 02:39
本帖最后由 何竹冬 于 2013-1-3 02:51 编辑
你好
这里有两个线程t线程和主线程在抢夺执行权。
如果t线程抢到执行权执行m1方法遇到sleep后t线程进入休眠状态放弃执行资格,休眠结束后进入线程池进入阻塞状态,也就是说有了执行资格没有执行权,等待被唤醒。
这时主线程获得执行权,执行m2方法时遇到sleep后主线程进入休眠状态放弃执行资格,休眠结束后进入线程池进入阻塞状态,这时主线程有执行资格没有执行权,等待被唤醒。
这时两个休眠线程都要被唤醒,线程池中等待的线程通常先进入的先被唤醒所以t线程先被唤醒打印b=1000后t线程结束放弃执行权,主线程获得执行权执行m2打印2000最后打印a=2000.
如果主线程抢到执行权同理可以得到打印结果2000,a=100,b=1000.
不过他们抢到执行权的机会是随机的,所以可能试很多次都只有一种结果,我试了n次才找到先打印b=1000的结果。你可以设置主函数和t线程的优先级然后在看一下打印结果。为了明显看到打印结果开启多个线程和主线程抢夺执行权。
01.package org.qyx.online;
public class TestSynchro implements Runnable {
int b = 100;
public synchronized void m1() throws Exception {
//System.out.println("m1 run");
b = 1000;
Thread.sleep(100);
System.out.println("b = " + b);
}
public synchronized void m2() throws Exception {
//System.out.println("m2 run");
Thread.sleep(250);
b = 2000;
System.out.println(b);
}
public void run() {
try {
m1();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
TestSynchro tt = new TestSynchro();
//设置主函数优先级最高
Thread.currentThread().setPriority(10);
for(int i=0;i<10;i++)
{
Thread t = new Thread(tt);
//设置t线程优先级最低
t.setPriority(1);
t.start();
}
tt.m2();
System.out.println("a =" + tt.b);
}
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2