线程方面的小问题

爱折腾的程序员 2013-12-11 03:48:24
public class SecondThread implements Runnable{
int i = 0;
public void run() {
for(i = 0;i < 50;i++){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}

public static void main(String[] args) {
for(int i = 0;i<50;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
if(i == 20){
Runnable target = new SecondThread();
new Thread(target, "task1").start();
new Thread(target, "task2").start();
}
}
}
}

执行了上面的代码,执行结果又这么一块
task1:41
task2:40
task2:42
就对这进行了分析,分析的结果如下
我的问题来了,既然target对象在内存的引用只有一份,在task1线程执行了i++后对内存中的i值就变成了41了,但是在轮到task2线程执行输出的时候值应该就是41了,不改是40.
...全文
213 4 打赏 收藏 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
william_yao 2013-12-12
  • 打赏
  • 举报
回复
我知道楼主的困惑,你觉得两个线程都共享这一个变量,那这个变量的值不应该顺序是这样。 这个时候你要明白,每个线程都有一个线程栈的,为了效率,采用了缓存策略,会将变量拷贝一份到自己的线程栈帧中,这样就没法保证第一时间获取到的是最新更新,或者更新了最新值了。 所以这时候如果使用,volatile关键字,就可以避免这种情况发生。 如果不明白,欢迎继续提问。 可以去看看《java并发编程指南》,就会很清楚了。
baiyewu19 2013-12-12
  • 打赏
  • 举报
回复
3个线程同时执行,谁抢到时间片运行都是随机的,什么打印都有可能啊,你多运行几次,每次的打印都不同的,楼主还是看看线程执行的机制吧
  • 打赏
  • 举报
回复
线程状态?没听过,还有相关资料吗
依然绿茶 2013-12-11
  • 打赏
  • 举报
回复
由于楼主你没有给这两线程同步,导致线程跑起来就比较随意,啥情况都有可能发生, 你说的就是这种情况: 本来task2将要执行打印task2 :40,结果由于System.out.println(Thread.currentThread().getName() + ":" + i);这句话调用还没结束(执行到一半),线程时间片被task1 抢占了(或者由于到时间了要放弃CPU),但是由于语句没执行完,打印没有输出,i的值是40,线程状态被保存,那么这个值也就被保存了(记住,是40) 好,继续走,轮到task1执行了,执行++i,值增大了1,那么接着打印了task1:41。 完了时间片到了,task2执行,取出上次保存的线程状态,发现i还是40,执行完打印语句(task2:40),又一次循环,这个时候由于task1已经将i的值编程41了,那么task2经过++i后,值变为42,输出打印task2:42 ——————这里面最重要的一点就是System.out.println(Thread.currentThread().getName() + ":" + i);这条语句没有执行完,但是i的值作为线程状态被保存起来了,因此下次取到的是个旧值。

62,620

社区成员

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

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