如何证明一个类不是线程安全的

3

我对线程并不是很了解。如何通过编写一个单独的类来证明MyClass类不是线程安全的?我一直在搜索,但无法找到帮助我的示例。

public class MyClass {
  private static int value = 0;
  
  public static void set(int setVal) {
    value = setVal;
  }

  public static int get() {
    return value;
  }  

  public static void decrement() {
    int temp = value;
    value = --temp;
  }
}

3
“我真的找不到一个能帮助我的例子。”这是因为测试线程安全性是不可靠的。当你运行一个不安全的程序时,许多不同的事情可能会发生。其中一些是不好的,一些则不是。不安全程序的行为可能会在在不同的机器上运行时变化,在不同的操作系统下运行, 在相同操作系统的不同版本下运行,不同的日子里运行,在同时运行其他不同程序的情况下运行,使用不同的编译器编译等等。 - Solomon Slow
哦,好的。是的,那很有道理。 - kai-san
也许是Void夫人?或者介于其中的某个东西。 - Curiosa Globunznik
天啊,你是对的。抱歉我做出了假设。 - kai-san
1
你不能仅凭代码就证明它是线程安全的。你需要进行分析,证明一个类 线程安全的,因为它正确地使用了synchronized或信号量,或者更难的是具有所有正确的happens-before关系:如果你无法证明这一点或者尚未尝试,则它就不是线程安全的。 - user207421
1个回答

2
public static void main(String[] args) {
    int nt = 10;
    int c = 20000;

    MyClass.set(c);

    Thread[] threads = new Thread[nt];

    for (int t = 0; t < nt; t++) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < c; i += nt) {
                MyClass.decrement();
            }
        });
        thread.start();
        threads[t] = thread;
    }

    try {
        for (Thread thread : threads) {
            thread.join();
        }
    } catch (Throwable tr) {
        tr.printStackTrace();
    }

    System.out.println(MyClass.get());
}

试一下。如果在MyClass的decrement方法中添加synchronized关键字,它将输出0(线程安全),但如果不同步减量操作,则会输出错误的数字。

这证明了MyClass(其减量方法)不是线程安全的,因为如果是,它应该输出0。

另外,如果无法使用lambda表达式,则将第一个for循环替换为以下内容:

for (int t = 0; t < nt; t++) {
    Thread thread = new Thread(() -> {
        for (int i = 0; i < c; i += nt) {
            MyClass.decrement();
        }
    });
    thread.start();
    threads[t] = thread;
}

希望我能够帮助您!


1
是的,谢谢IntoVoid先生!现在我要好好理解它。 - kai-san

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接