有人可以向我解释一下我所缺少的吗:当我调用<CONTYPE>2</CONTYPE>
时,我认为两个线程都应该在1s内执行,所以之后为什么我应该将Thread.sleep(1000)
设置为false以在1s内停止线程
为什么doSlice
不会在一秒钟内阻止他们。我的意思是1s之后的run方法甚至不应该在条件检查时调用:
Thread.sleep()
答案 0 :(得分:3)
有人可以向我解释我所缺少的吗
您缺少的是线程之间的memory synchronization。当您启动2个后台线程时,它们具有自己的本地内存(在自己的CPU上),您需要专门更新它们之间的所有共享数据。
使代码复杂化的是,System.out.println(...)
是一种同步方法,因此它“免费”为您提供了一些内存同步,但是您不应依赖它(请参见下文)。这意味着,如果删除该调试代码,则程序的行为将有所不同。小心在线程代码中使用System.out.print*
。
Thread.sleep(1000);
运行此sleep命令时,它将使主线程进入睡眠状态,但2个后台线程继续运行。他们每个人都在更新自己的slice_count
副本,但不能保证主线程会看到这些更新。
// need to add the volatile keyword here
private volatile int slice_count;
通过将volatile
Java keyword添加到slice_count
,这会将字段标记为被多个线程访问。当主线程访问slice_count
时,它将读取它的最新值。您可能还想研究AtomicInteger
,它包装了volatile int
,但允许多个线程执行类似incrementAndGet()
的操作。
存在内存同步问题的另一个地方是:
executionScheduling.doSlice = false;
executionScheduling1.doSlice = false;
因此,doSlice
字段也需要为volatile
:
// need to add the volatile keyword here
public volatile boolean doSlice = true;
最后,没有顺序:
您的字段应尽可能为private
。
应为executionScheduling1
和executionScheduling2
。
定义Runnable
而不是Thread
是更好的模式。参见:https://stackoverflow.com/a/541527/179850
您可能考虑在打印输出结果之前,先进行join()
等待或每个线程完成其工作。
// set the doSlices to false
executionScheduling.join()
executionScheduling1.join()
// printf results
如果您添加join()
调用,那么它将以slice_count
的名义为您处理内存同步,因此只要您访问它们,它们就不再需要volatile
在join()
调用结束之后>。是的,这令人困惑。线程编码是不平凡的。您仍然需要将doSlice
字段设置为volatile
,因为它们是在{em> join()
完成之前被访问的。