Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从多个线程测试类的线程安全性?_Java_Multithreading_Thread Safety - Fatal编程技术网

Java 如何从多个线程测试类的线程安全性?

Java 如何从多个线程测试类的线程安全性?,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我正在处理线程安全的单例类,我知道下面的代码不是线程安全的,因为我正在进行双重检查锁定错误 protected static TestSingleton instance; private TestSingleton() { // some code } public static synchronized void setup() { if (instance == null) { TestSingleton holder = new TestSinglet

我正在处理线程安全的单例类,我知道下面的代码不是线程安全的,因为我正在进行双重检查锁定错误

protected static TestSingleton instance;

private TestSingleton() {
    // some code
}

public static synchronized void setup() {
    if (instance == null) {
        TestSingleton holder = new TestSingleton();
        instance = holder;
    }
}

public static TestSingleton getInstance() {
    if (instance == null) {
        setup();
    }
    return instance;
}
但我正试图对此进行测试,以便通过编程证明这不是线程安全的类。这是我的学习经历


如何以编程方式测试它并证明它不是线程安全的

我明白了为什么我下面的回答不正确。有关原因,请参阅相关评论帖子

我认为不可能证明您的程序在其当前版本中不是线程安全的,因为方法内部的逻辑足够“安全”

这是因为,即使可能会尝试同时调用getInstance()内部的setup()调用,setup()内部的逻辑也会同步发生,因为方法声明为synchronized


假设您有两个线程,A和B,竞争对setup()的访问权。A首先在实例变量中设置对TestSingleton对象的引用。当A在setup()方法中时,B尝试调用它并被阻止。A结束,B进入方法。由于instance现在不为null,因此setup()中的任何逻辑都不会被B调用。因此,在setup()中的条件块中,您永远不会看到逻辑的多次调用。

我已经了解了我下面的响应不正确的原因。有关原因,请参阅相关评论帖子

我认为不可能证明您的程序在其当前版本中不是线程安全的,因为方法内部的逻辑足够“安全”

这是因为,即使可能会尝试同时调用getInstance()内部的setup()调用,setup()内部的逻辑也会同步发生,因为方法声明为synchronized


假设您有两个线程,A和B,竞争对setup()的访问权。A首先在实例变量中设置对TestSingleton对象的引用。当A在setup()方法中时,B尝试调用它并被阻止。A结束,B进入方法。由于instance现在不为null,所以setup()中的任何逻辑都不会被B调用。因此,在setup()中的条件块中,您将永远不会看到对逻辑的多次调用.

通过您描述的测试,您最有可能寻找的是两个线程从其
getInstance()
方法获取不同的
TestSingleton
实例,或者一个线程从该方法获取
null
返回值,或者一个线程在实例完全初始化之前返回实例

问题是,你无法确定这些事情发生的可能性有多大,事实上,它们发生的可能性很小。您可能会运行大量的测试迭代,而不会看到任何失败行为。如果您确实看到了其中一个,那么您已经证明了程序不是线程安全的,但是没有看到任何一个都不能证明什么


线程安全性是一个程序属性,您必须通过分析程序来证明它。它不能通过在有限时间内进行测试来证明。

通过您所描述的测试,您最可能要寻找的是两个线程从其
getInstance()
方法中获取不同的
TestSingleton
实例,或者一个线程从该方法中获取
null
返回值,或者在实例完全初始化之前返回实例的线程

问题是,你无法确定这些事情发生的可能性有多大,事实上,它们发生的可能性很小。您可能会运行大量的测试迭代,而不会看到任何失败行为。如果您确实看到了其中一个,那么您已经证明了程序不是线程安全的,但是没有看到任何一个都不能证明什么


线程安全性是一个程序属性,您必须通过分析程序来证明它。这不能通过有限时间的测试来证明。

归结起来就是:您的程序有一定数量的线程,运行在一定数量的处理器上,但您的计算机只有一个主内存

每个线程将以某种顺序读写不同的内存位置,这在某种程度上与其他线程的操作无关;所有这些读写操作在进入内存时都必须序列化。也就是说,内存系统必须逐个执行这些读写操作

对于多线程程序的任何给定执行,可以有无数种不同的方式来序列化不同线程的操作。从字面上说,太多了,数不清。如果哪怕是其中一种可能的序列化都会导致程序产生错误的输出,那么程序就不是线程安全的

那么你如何测试它们呢

你不能。它们太多了,可能在一台计算机(例如,您客户的任务关键型服务器)上频繁发生的序列化可能永远不会在其他计算机(例如,您的测试线束)上发生


确保线程安全的唯一方法是使用经过数学验证的算法来同步线程的操作,这样就不会发生错误的交错。

归结起来就是:您的程序有一定数量的线程,在一定数量的处理器上运行,但您的计算机只有一个主内存

每个线程将以某种顺序读写不同的内存位置,这在某种程度上与其他线程的操作无关;所有这些读写操作在进入内存时都必须序列化。也就是说,内存系统必须逐个执行这些读写操作

对于多线程程序的任何给定执行,可以有无数种不同的方式来序列化不同线程的操作。从字面上说,太多了,数不清。即使是其中一个