请大伙帮我看个多线程的代码,很简单

livs_ly_2010 2009-10-19 03:22:04
import java.util.*;
public class TT implements Runnable{
public int i =100;
public synchronized void m1(){
i=1000;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i="+i);
}
public void m2(){
i=2000;
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
m1();
}
public static void main(String [] args){
TT tt = new TT();
Thread tr=new Thread(tt);
tr.start();
tt.m2();

}
}


说出输出什么,为什么。
...全文
420 59 打赏 收藏 转发到动态 举报
写回复
用AI写文章
59 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuzuru 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 50 楼 annchaling 的回复:]

补充下:楼主第一楼的问题的确与sleep无关,但是16L的问题结果由sleep时间决定,并不是主线程阻隔的问题.楼主的问题我觉得用16L的代码最能体现出这个问题的实质.
[/Quote]

16楼的代码,和我在tr.start();和tt.m2();之间加上Thread.sleep(1);本质相同,都是让m2方法赋值语句晚一点执行,具体说就是在m1线程sleep的时候执行。
安小寰 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 48 楼 yuzuru 的回复:]
前面说过了,1000、2000都有可能,和sychronized无关。但实际运行肯定是1000。
详细解释一下吧。
首先,这个问题和synchronized无关。你的synchronized又没有锁变量,这里也不是2个线程调m1,所以synchronized是没影响的。
这个和sleep时间也没有关系。就是主线程的tt.m2()和tr谁先谁后,输出后执行里的那个赋值。
你在tr.start();和tt.m2();之间加上Thread.sleep(1);模拟主线程被阻隔的效果,就输出2000了。

[/Quote]
补充下:楼主第一楼的问题的确与sleep无关,但是16L的问题结果由sleep时间决定,并不是主线程阻隔的问题.楼主的问题我觉得用16L的代码最能体现出这个问题的实质.
humcomm 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 44 楼 annchaling 的回复:]
另外,楼上很多人说的synchronized锁定的是对象内部的变量或方法的说法是不正确的.
[/Quote]
同意,锁的是对象
yuzuru 2009-10-20
  • 打赏
  • 举报
回复
前面说过了,1000、2000都有可能,和sychronized无关。但实际运行肯定是1000。
详细解释一下吧。
首先,这个问题和synchronized无关。你的synchronized又没有锁变量,这里也不是2个线程调m1,所以synchronized是没影响的。
这个和sleep时间也没有关系。就是主线程的tt.m2()和tr谁先谁后,输出后执行里的那个赋值。
你在tr.start();和tt.m2();之间加上Thread.sleep(1);模拟主线程被阻隔的效果,就输出2000了。
弘石 2009-10-20
  • 打赏
  • 举报
回复
因此楼主16楼的结果就很明显了,m1先赋值,m2后赋值,并且m1是在m2执行后进行打印,所以打印结果是2000
弘石 2009-10-20
  • 打赏
  • 举报
回复
前面的认识是错的
根据44楼所说的进一步测试了一下,前面的是错的,44楼是正确的
kent4j 2009-10-20
  • 打赏
  • 举报
回复
严重同意楼上的最后一句话
安小寰 2009-10-20
  • 打赏
  • 举报
回复
对照了API重新总结了下楼主提出的问题:
1.首先,synchronized关键字不管加在类声明上还是加在方法声明上,它所作的工作只是锁定对象,而对于其内部的方法和变量不做“私有”锁定.也就是同一对象就算有synchronized但是其中同一变量还是能被对象中不同方法访问.
2.接下来看楼主提出的问题,从main开始,到tr线程start(),此时开始有tr线程和main线程同步执行,在楼主的程序中,线程执行先被main抢占,执行完i=2000,然后main开始sleep()挂起,tr线程执行i=1000,然后sleep()到结束.tr线程执行最后打印i=1000.至于为什么先执行的是main线程中的i赋值,这是jvm内部机制决定的,在此不做探讨.
3.下面问题的重点来了,究竟synchronized有没有锁定i.楼主可以用下面这段代码测试下:
public static void main(String [] args){
TT tt = new TT();
Thread tr=new Thread(tt);
tr.start();
System.out.println("1");
tt.m2();
}
在tt.m2()执行之前执行一个额外的方法.此时线程的调用过程变为:
(1)System.out.println("1");被首先执行,main线程时间片使用完毕
(2)tr线程开始执行i=1000,开始sleep()休眠(注意,此时tr线程并未结束,synchronized仍旧锁定对象).
(3)main线程执行tt.m2(),i=2000赋值成功,开始休眠(若是i被锁定,m2此时不应该能访问)
(4)tr休眠结束(应该说是m2()休眠先结束,没影响),执行打印方法.

综上,如前所述,解释了楼主提出的问题.而后面提出的测试代码的分析就是楼主第二个问题的答案:
因为m2()中先进行休眠,tr线程中首先赋值i=1000然后休眠,在tr休眠未结束之前m2()被唤醒执行i=2000,所以tr线程执行到打印方法时i的值已经为2000了.

另外,楼上很多人说的synchronized锁定的是对象内部的变量或方法的说法是不正确的.
yingShisscWang 2009-10-20
  • 打赏
  • 举报
回复
#44楼太强,膜拜一下
yingShisscWang 2009-10-20
  • 打赏
  • 举报
回复
关键一点:
tt.m2();坑定100%比m1()先执行。
我觉得这可能是因为tt.m2()属于main,而主线程优先级尤其高的关系。

所以绝对是输出1000
16的代码在tt.m2()中将i的赋值语句置于sleep之后了,所以为m1()争取了时间

ps:和synchronized 无关
livs_ly_2010 2009-10-20
  • 打赏
  • 举报
回复
还是感谢大家的回答,谢谢大家踊跃回答。
haojia0716 2009-10-20
  • 打赏
  • 举报
回复
呵呵
yangbing694383929 2009-10-20
  • 打赏
  • 举报
回复
bangding!
fsn011362 2009-10-20
  • 打赏
  • 举报
回复
还没仔细看过多线程呢
dm520 2009-10-20
  • 打赏
  • 举报
回复
m2()调完 就回调m1() 不会等待5秒后
dm520 2009-10-20
  • 打赏
  • 举报
回复
应该是2000
tr.start(); 调用了run() ----m1()sleep(5000)
这时调用了m2() 给i重新赋值为2000
晴天v1 2009-10-19
  • 打赏
  • 举报
回复
[Quote=引用 42 楼 zhangyou1010 的回复:]
2000
[/Quote]
晕,猜错了,希望#35楼说的是正确的,学习了,3q.
晴天v1 2009-10-19
  • 打赏
  • 举报
回复
2000
EmperorsE 2009-10-19
  • 打赏
  • 举报
回复
只会输出一次,1000.
m2虽然运行了。但没有输出结果。
springbird 2009-10-19
  • 打赏
  • 举报
回复
学习了
加载更多回复(39)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧