【问题标题】:Java threads - variables local to the threadJava 线程 - 线程本地的变量
【发布时间】:2011-05-14 04:05:46
【问题描述】:

我很难理解 Java 线程的工作原理,所以请原谅这个相当简单的问题。

假设我有一个包含 N 个线程的程序。每个线程在字符串数组的不同部分执行相同的指令。我们通过具有可运行接口的类调用线程。就本示例而言,假设它是这样的:

run() {
    while (startStop = loopGetRange() != null) {

        countLetters(startStop.start,startStop.stop);
        /* start is the beginning cell in the array where the process starts
          and stop is the ending cell in the array where the process stops */
    }
}

最后 countLetters 只是一个简单的方法如下:

private void countLeters (int start, int stop) {
    for (int y = start; <= stop; y++) {
        String theWord = globalArray[y];
        int z = theWord.length;
        System.out.println("For word "+theWord+" there are "+z+" characters");
    }
}

这是我的问题:像“theWord”和“Z”这样的变量是线程本地的,还是它们在线程之间共享,因此可能会发生线程冲突。如果是后者,如何最好地保护这些变量。

感谢您帮助困惑的人。

艾略特

【问题讨论】:

    标签: java thread-safety


    【解决方案1】:

    局部变量在堆栈上分配,并且对于线程是局部的。只有成员字段在线程之间共享。因此,theWordZ 不会跨线程共享,您无需担心冲突。

    鉴于 String 是不可变的,我们在方法 countLeters() 中唯一关心的线程安全就是访问 globalArray。

    现在,如果这个数组的构造“发生在”访问 globalArray 之前,只要没有线程“写入”到 globalArray,代码就是安全的。

    "happened-before" 关系可以通过多种方式强制执行(通过使用synchronized 关键字、final 关键字、volatile 关键字、使用java.util.concurrent 库等)。

    【讨论】:

    • 太棒了。这很清楚。谢谢你的解释。
    【解决方案2】:

    线程对可见的变量没有影响。就像您创建了类并在不启动线程的情况下运行了该方法一样。如果多个线程将访问相同的对象,那么您必须考虑使用锁来确保它们不会相互踩踏。

    【讨论】:

    • 如果你有一个线程池来工作,可以为每个线程跟踪线程局部变量。静态变量将在此可运行的所有实例之间共享。
    • 是的,有 ThreadLocal,但这看起来不像他在这里问的那样。
    【解决方案3】:

    就像 JOTN 所说,如果线程正在访问相同的对象,那么可能会发生线程冲突。

    如果在这种情况下globalArray 变量在线程间共享,并且尤其是如果它或其元素被修改,那么使用锁可能是明智的/同步。

    【讨论】:

    • 好的。全局数组未被修改。我更关心 countLetters 方法中的变量。在运行中调用的方法。如果我理解正确,那么 countLetters 方法的局部变量似乎可能会受到结论的影响。它是否正确?如果是这样,我不是将 countLetters 作为方法调用,而是创建了一个名为 Count letters 的类,它调用包装的方法作为其实例化的一部分,这样可以解决问题吗?
    • 我不太清楚你所说的“以结论为准”是什么意思。但是在方法中创建的变量是方法的本地变量。但是,在您编写的示例中,您执行String theWord = globalArray[y];,其中 theWord 成为对gloablArray[y] 对象的引用。我不确定将它包装在一个类中会有所不同。
    【解决方案4】:

    除了变量的可见性和共享变量的锁定/同步问题...

    像“theWord”和“Z”这样的变量是线程本地的吗

    您询问的那些变量是循环的局部变量,而不是类或实例的一部分,并且存在于每个线程的基础上,因此不会发生任何冲突。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-07
      • 2011-11-16
      • 1970-01-01
      • 2020-05-13
      • 1970-01-01
      • 2018-08-28
      • 2016-11-30
      相关资源
      最近更新 更多