package test1;

import java.util.Random;

public class OneInstanceService {
    // use volatile or final,them has same effect,
    // but difference volatile or final in DCL demo?
    public int i_am_has_state;

    private static OneInstanceService test;

    private OneInstanceService() {
        i_am_has_state = new Random().nextInt(200) + 1;
    }

    public static OneInstanceService getTest1() {
        if (test == null) {
            synchronized (OneInstanceService.class) {
                if (test == null) {
                    test = new OneInstanceService();
                }
            }
        }
        return test;
    }

    public static void reset() {
        test = null;
    }

}


//----------------------------------------
package test1;

import java.util.concurrent.CountDownLatch;

public class Test1 {
    public static void main(String[] args) throws InterruptedException {
        for (;;) {
            CountDownLatch latch = new CountDownLatch(1);
            CountDownLatch end = new CountDownLatch(100);
            for (int i = 0; i < 100; i++) {
                Thread t1 = new Thread() {
                    @Override
                    public void run() {
                        try {
                            latch.await();
                            OneInstanceService one = OneInstanceService.getTest1();
                            if (one.i_am_has_state == 0) {
                                System.out.println("one.i_am_has_state == 0 process exit");
                                System.exit(0);
                            }
                            end.countDown();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                };
                t1.start();
            }
            latch.countDown();
            end.await();
            OneInstanceService.reset();
        }
    }
}


仅使用:

public int i_am_has_state;


运行结果是:

System.out.println("one.i_am_has_state == 0 process exit");
System.exit(0);


但修改代码底部:

volatile public int i_am_has_state;


要么

final public int i_am_has_state;


没有运行底部代码:

System.out.println("one.i_am_has_state == 0 process exit");
System.exit(0);


我的问题是:
DCL使用最后确定
DCL使用最终挥发性好

所以
在DCL中最终和挥发性的区别?

非常感谢你 !

最佳答案

final和volatile无法放在一起,因为它们是故意相反的。

或者您有一个静态字段,它在类init时初始化过:

static final Object x;
static {
    x = ...
}


或者您有一个可变的静态字段,多个线程可以争用设置(您的情况)。

为了使双重检查惯用语言起作用,它必须是可变的(自jdk 1.5起使用新的可变语义)。从那时起,volatile就具有防止其他变量涉及的指令重新排序的内存屏障,这(以某种方式使我(现在不记得了……)使丑陋的DCL再次起作用...但并没有使其变得丑陋。

(我从来不需要使用DCL;没有DCL,因为if(x==null)是如此之快,所以同步仍然基本上没有竞争性。)

09-28 11:27