• 执迷不悟

    书中66页底部讲到 volatile关键字可以保证内存可见性和避免重排序
    那么假设如下变量顺序

    a
    b
    volatile c
    d
    e

    是c前后都不会重排序了吗?还是{a, b可以随便动,c不动, d, e可以随便动}
    恳请作者给出解释,感谢!

    执迷不悟发表于 2020/3/20 1:20:01
    • 翟陆续

      volatile具有下面happen-before语义,来避免指令重排序:

      当修改一个volatile变量时候,可以保证其前面对其他变量的读写操作,不会被重排序到写volatile变量操作后面。
      读取一个volatile变量时候,可以保证其后面对其他变量的读写操作,不会被重排序到读volatile变量前面

      翟陆续发表于 2020/7/4 11:32:11
  • hyl08

    书中第二章 讲指令重排的代码 为什么自己运行多次后的结果没有出现为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");
        }
    }`
    
    hyl08发表于 2020/3/11 10:29:27
    • 执迷不悟

      我也没出现,我还试了多开点线程竞争,for循环多次,都没出现

      执迷不悟发表于 2020/3/20 12:53:27
    • 翟陆续

      @执迷不悟 指令重排序发生需要一定条件,书中例子只是为了说明指令重排序现象。

      翟陆续发表于 2020/7/4 11:35:38
  • jamesfuxk

    第10章的3.1 的第二个例子的结果输出有误。

    jamesfuxk发表于 2020/1/5 2:18:43
  • issxjl2015

    是否会公布书中源码?如果没有的话,打算自己敲一遍

    issxjl2015发表于 2019/11/3 20:17:57
  • mutech

    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 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();前面,虽然能解决,但是也有问题,没阻塞前就被输出了。
    前面的例子也有这样的问题,这两个例子都是同样情况。

    mutech发表于 2019/7/15 1:03:30
    • 翟陆续

      是的,你分析的很对,书中只是写出了一种情况下的结果,这个在新版里面已经修改过了(输出语句放到Thread.sleep(1000);后面)。

      翟陆续发表于 2019/7/19 20:07:54
    • 翟陆续

      @翟陆续 另外这里 System.out.println("child threadA over");意在表述try子线程内任务执行完毕了,并不是说子线程终止了

      翟陆续发表于 2019/7/19 20:09:54
  • 1
  • 2
  • 3
  • 4
  • 5