当前位置:  开发笔记 > 编程语言 > 正文

代码中的奇怪行为,用于测试线程安全的单例

如何解决《代码中的奇怪行为,用于测试线程安全的单例》经验,为你挑选了2个好方法。

我对Java中的多线程很新.因为我需要一个线程安全的单例(我实现为枚举),我写了一个小的测试代码,它会产生一个奇怪的输出.

代码:

public enum EnumSingleton {
    INSTANCE;


    /** state variables */
    private String message;

    /** Constructor */
    private EnumSingleton() {
    }

    /** add well-known accessor for the instance  (is NOT necessary) */
    public static EnumSingleton getInstance() {
        return INSTANCE;
    }


    /** Accessors */
    public String getMessage() {
        return message;
    }

    public void setMessage(String name) {
        this.message = name;
    }
}

public class App {

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            final int b = i;
            Thread thread = new Thread("Thread #" + b) {
                @Override
                public void run() {
                    EnumSingleton singleton = EnumSingleton.getInstance();
                    singleton.setMessage("Message written by "+this.getName());
                    System.out.println("Current thread "+this.getName() + ": "+singleton.getMessage());
                }
            };
            thread.start();
        }
    }
}

因此,每个线程将其名称写入枚举的属性"message"中,然后将其打印到STDOUT.我得到以下输出,我觉得很奇怪:

Current thread Thread #6: Message written by Thread #3
Current thread Thread #1: Message written by Thread #1
Current thread Thread #8: Message written by Thread #8
Current thread Thread #5: Message written by Thread #1
Current thread Thread #4: Message written by Thread #4
Current thread Thread #9: Message written by Thread #9
Current thread Thread #7: Message written by Thread #3
Current thread Thread #2: Message written by Thread #3
Current thread Thread #0: Message written by Thread #3
Current thread Thread #3: Message written by Thread #3

我期望的是我得到每个循环计数器(0-9)一条消息.但是在这个例子中我有多个由Thread#3写的消息,那怎么可能呢?有竞争条件吗?

如果我的代码是废话:我如何正确测试我的单例以获得线程安全?



1> Tim B..:

这里有一个明确的竞争条件,因为你message在枚举的单例实例中有一个变量.你的线程都在同时写入和读取该变量,所以你希望看到这样的结果.

枚举构造意味着单个对象的创建是线程安全的,但是仍然需要正确处理对其中的方法的调用.

你正在寻找的方法是message成为一个线程局部变量,或者将消息的设置和它的读取放在一个单独的synchronized块中,可能锁定单例对象.



2> assylias..:

单例不是线程安全的 - 你没有做任何事情来保证message变量的可见性.

你可以做到这volatile一点.但请注意,输出可能是许多不同的东西-特别是你不一定会得到一个Message written by Thread #i每个i.

推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有