多线程求和 , 线程run中添加System.out和不添加System.out是两种结果

HLhakey 2017-08-17 10:21:51
主类:


package thread.worker;

import org.junit.Test;

/**
* Created by hu on 2017/8/17.
*/
public class CountWorker {
protected int sum = 1;

@Test
public void testWorker() {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new CountThread(this));
thread.setName("huli" + i);
thread.start();
}

System.out.println("sum = " + sum);
}
}


计算类:

package thread.worker;

/**
* Created by hu on 2017/8/17.
*/
public class CountThread implements Runnable {
private CountWorker countWorker;

public CountThread(CountWorker countWorker) {
this.countWorker = countWorker;
}

@Override
public void run() {
while (countWorker.sum < 20) {
System.out.println("sum is : " + countWorker.sum);
countWorker.sum++;
}
}
}


一次运行结果为:

sum = 20
sum = 21
sum = 23



问: 为什么会大于20 ?

结论一: 当我去掉 countWorker.sum++;前的

System.out.println("sum is : " + countWorker.sum);

时, 结果一般都为20 , 正确结果, 加上

System.out.println("sum is : " + countWorker.sum);

就会大于20 , 为什么 ?
...全文
264 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
HLhakey 2017-08-19
  • 打赏
  • 举报
回复
引用 5楼Phantom蓝墨 的回复:
[quote=引用 4 楼 HLhakey 的回复:] 我理解的是, 在++的外层有一个while 判断 , 那么线程进入到while 体内 就应该是满足条件的 , 所以不应该出现大于规定数值的情况.
你还没理解线程安全问题,有时候会出现这样一个情况:假设有AB两个线程,此时sum=19,A线程先进行判断sum<20,执行syso的时候(sum还未自增),B线程开始判断sum<20,由于A线程还未执行sum++,所以此时sum还是19;也进入最后AB两个线程都会执行sum++的操作,导致sum=21.[/quote]我理解你说的这个,那我有一个问题,两个线程进入while中时都是19 ,是同一个19吗? 是各自的19吧,你的意思是A线程对sum的+1操作是对B线程可见的?还是out打印时线程去主存储取一次指,sum++时又去取了一次。如果是这种解释就理解了。
wautsns 2017-08-18
  • 打赏
  • 举报
回复
引用 4 楼 HLhakey 的回复:
我理解的是, 在++的外层有一个while 判断 , 那么线程进入到while 体内 就应该是满足条件的 , 所以不应该出现大于规定数值的情况.
你还没理解线程安全问题,有时候会出现这样一个情况:假设有AB两个线程,此时sum=19,A线程先进行判断sum<20,执行syso的时候(sum还未自增),B线程开始判断sum<20,由于A线程还未执行sum++,所以此时sum还是19;也进入最后AB两个线程都会执行sum++的操作,导致sum=21.
110成成 2017-08-18
  • 打赏
  • 举报
回复
加了打印信息,相当于增加了延时,使问题更容易复现而已 你可以加sleep,道理是一样的。
HLhakey 2017-08-18
  • 打赏
  • 举报
回复
引用 1 楼 phantom7493 的回复:
循环出来的10个线程共用了一个CountWorker对象(即this),而你并没有使用线程锁之类的方式导致了线程安全问题,因为system.out.println()需要一定的执行时间,相当于给sum++;加了一点延迟,所以这个问题更容易出现.
我理解的是, 在++的外层有一个while 判断 , 那么线程进入到while 体内 就应该是满足条件的 , 所以不应该出现大于规定数值的情况.
HLhakey 2017-08-18
  • 打赏
  • 举报
回复
引用 2 楼 zc881124 的回复:
加了打印信息,相当于增加了延时,使问题更容易复现而已 你可以加sleep,道理是一样的。
不加的话一定是对的吗? 这个是为什么.
wautsns 2017-08-17
  • 打赏
  • 举报
回复
循环出来的10个线程共用了一个CountWorker对象(即this),而你并没有使用线程锁之类的方式导致了线程安全问题,因为system.out.println()需要一定的执行时间,相当于给sum++;加了一点延迟,所以这个问题更容易出现.

50,549

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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