书中66页底部讲到 volatile关键字可以保证内存可见性和避免重排序那么假设如下变量顺序
abvolatile cde
是c前后都不会重排序了吗?还是{a, b可以随便动,c不动, d, e可以随便动}恳请作者给出解释,感谢!
volatile具有下面happen-before语义,来避免指令重排序: 当修改一个volatile变量时候,可以保证其前面对其他变量的读写操作,不会被重排序到写volatile变量操作后面。 读取一个volatile变量时候,可以保证其后面对其他变量的读写操作,不会被重排序到读volatile变量前面
书中第二章 讲指令重排的代码 为什么自己运行多次后的结果没有出现为0的结果 代码和书中的一致
`public static void main(String[] args) throws Exception { ReadThread read = new ReadThread(); WriteThread write = new WriteThread(); read.start(); write.start(); Thread.sleep(10); read.interrupt(); }
private static int num = 0; private static boolean ready = false; static class ReadThread extends Thread { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { if (ready) { System.out.println(num + num); } } System.out.println("read over"); } } static class WriteThread extends Thread { @Override public void run() { num = 2; ready = true; System.out.println("write over"); } }`
我也没出现,我还试了多开点线程竞争,for循环多次,都没出现
@执迷不悟 指令重排序发生需要一定条件,书中例子只是为了说明指令重排序现象。
第10章的3.1 的第二个例子的结果输出有误。
是否会公布书中源码?如果没有的话,打算自己敲一遍
10.1小节中(p258-259)这么一段代码public class Section01Demo0002 { // 创建一个CountDownLatch实例 private static final j**a.util.concurrent.CountDownLatch countDownLatch = new j**a.util.concurrent.CountDownLatch(2);
public static void main(String[] args) throws InterruptedException { j**a.util.concurrent.ExecutorService executorService = j**a.util.concurrent.Executors.newFixedThreadPool(2); // 将线程A添加到线程池 executorService.submit(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } System.out.println("child threadA over"); }); // 将线程B添加到线程池 executorService.submit(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } System.out.println("child threadB over"); }); System.out.println("wait all child thread over"); // 等待子线程执行完毕 countDownLatch.await(); System.out.println("all child thread over"); executorService.shutdown(); }
我们本地执行的结果是wait all child thread overchild threadA overall child thread overchild threadB over
Process finished with exit code 0
有时也会出现您书中所写的wait all child thread overchild threadB overchild threadA overall child thread over
子线程执行完countDownLatch.countDown();后它的时间片用完了,主线程获取到了时间片先输出了,然后子线程又获取到了时间片,继续输出,才有了这样结果,应该把System.out.println(“child threadA over”);放到countDownLatch.countDown();前面,虽然能解决,但是也有问题,没阻塞前就被输出了。前面的例子也有这样的问题,这两个例子都是同样情况。
是的,你分析的很对,书中只是写出了一种情况下的结果,这个在新版里面已经修改过了(输出语句放到Thread.sleep(1000);后面)。
@翟陆续 另外这里 System.out.println("child threadA over");意在表述try子线程内任务执行完毕了,并不是说子线程终止了
书中66页底部讲到 volatile关键字可以保证内存可见性和避免重排序
那么假设如下变量顺序
a
b
volatile c
d
e
是c前后都不会重排序了吗?还是{a, b可以随便动,c不动, d, e可以随便动}
恳请作者给出解释,感谢!
书中第二章 讲指令重排的代码 为什么自己运行多次后的结果没有出现为0的结果 代码和书中的一致
`public static void main(String[] args) throws Exception {
ReadThread read = new ReadThread();
WriteThread write = new WriteThread();
read.start();
write.start();
Thread.sleep(10);
read.interrupt();
}
第10章的3.1 的第二个例子的结果输出有误。
是否会公布书中源码?如果没有的话,打算自己敲一遍
10.1小节中(p258-259)这么一段代码
public class Section01Demo0002 {
// 创建一个CountDownLatch实例
private static final j**a.util.concurrent.CountDownLatch countDownLatch = new j**a.util.concurrent.CountDownLatch(2);
我们本地执行的结果是
wait all child thread over
child threadA over
all child thread over
child threadB over
Process finished with exit code 0
有时也会出现您书中所写的
wait all child thread over
child threadB over
child threadA over
all child thread over
Process finished with exit code 0
子线程执行完countDownLatch.countDown();后它的时间片用完了,主线程获取到了时间片先输出了,然后子线程又获取到了时间片,继续输出,才有了这样结果,应该把System.out.println(“child threadA over”);放到countDownLatch.countDown();前面,虽然能解决,但是也有问题,没阻塞前就被输出了。
前面的例子也有这样的问题,这两个例子都是同样情况。