【问题标题】:Java multi-threading threads terminating at randomJava多线程线程随机终止
【发布时间】:2023-03-28 02:13:01
【问题描述】:

在学习 Java 并发时,我遇到了这种我无法解释的行为:

public class ThreadInterferrence implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new ThreadInterferrence());
        t.start();
        append("1", 50);
        t.join();
        System.out.println(value);
    }

    private static String value = "";

    public void run() {
        append("2", 50);
    }

    private static void append(String what, int times) {
        for (int i = 0; i < times; ++i) {
            value = value + what;
        }
    }
}

为什么程序会生成随机字符串?更重要的是为什么输出的长度不同?它不应该总是正好 100 个字符吗?

输出示例:

22222222222222222222222222222222222222222222222222
1111111111111111111111111111112121112211221111122222222222222

等等。

【问题讨论】:

    标签: java string multithreading concurrency terminate


    【解决方案1】:

    原因是你有两个线程。

    • 附加到相同值字符串的主线程
    • ThreadInterferrence 线程再次附加到相同的值字符串。

    是操作系统 (OS) 在调度运行哪个线程,因此您会看到随机输出。因此,在您的情况下,操作系统会安排您的 runnable 暂时运行,打印 1,然后尝试运行主线程,然后再打印 2。

    【讨论】:

    • 好的,我一直跟着你。但是为什么输出String的长度会变化呢?无论顺序如何,不应该总是正好 100 个字符吗?
    【解决方案2】:

    关于您更新问题的主题(为什么输出的长度会有所不同?它不应该总是正好 100 个字符吗?)

    行为将是不可预测的,因为新字符串的重新分配不是原子的。请注意,字符串是不可变的,并且您不断将值重新分配给变量。所以发生的事情是一个线程获取值,另一个线程也获取值,一个线程添加一个字符并再次写入,但另一个线程使用旧值也是如此。现在您正在丢失数据,因为其中一个线程的更新丢失了。

    在这种情况下,您可以使用线程安全的 StringBuffer,或者添加同步,我相信您会了解的。

    【讨论】:

      【解决方案3】:

      [问题]更重要的是为什么输出的长度会变化?

      [Answer] 变量“value”被多个线程(主线程和其他线程)使用。因此,用于更改变量状态的方法需要是线程安全的,以控制最终长度。这里情况不同。

      【讨论】:

        猜你喜欢
        • 2014-11-18
        • 2012-08-28
        • 1970-01-01
        • 1970-01-01
        • 2015-12-21
        • 2011-08-11
        • 1970-01-01
        • 2023-02-20
        • 1970-01-01
        相关资源
        最近更新 更多