java - 多线程:将实例和局部变量传递给线程

标签 java multithreading thread-safety

我对将实例和局部变量作为参数传递给线程有疑问。

让我向您展示一个简短的示例:

public class Foo {
    private int num;
    private String str;

    public Foo(int num, String str){
        this.num = num;
        this.str = str;
    }

    public int getNum() {
        return num;
    }

    public String getStr() {
        return str;
    }
}


public class FooRunnable implements Runnable {

    private Foo foo;

    public FooRunnable(Foo foo){
        this.foo = foo;
    }

    @Override
    public void run() {
        System.out.println("Number =" +foo.num);
        System.out.println("String =" +foo.str);    
    }
}

public class Test {

private Foo fooField;

public Test(){
    fooField = new Foo(4, "four");
}

public void launchField(){
    Thread th = new Thread(new FooRunnable(fooField));
    th.start();
}

public void launchLocalVariable(){
    Foo fooLocal = new Foo(5,  "five");
    Thread th = new Thread(new FooRunnable(fooLocal));
    th.start();
}

public static void main(String[] args) {
    Test test =  new Test();
    test.launchField();
    test.launchLocalVariable();
}

}

这只是一个启动两个线程的愚蠢程序:一个将实例变量作为参数传递给线程,另一个传递局部变量。随后,两个线程将传递的参数中的内容写入控制台。

对于局部变量,我确信它的行为是线程安全的。在第二种情况下,我认为不会,因为可能会缓存该变量。你怎么看待这件事?我错了吗?

最佳答案

很简单:如果信息可以通过线程改变,那么你总是需要担心线程安全。

重要的部分是:改变的能力。

在您的示例中,Foo 的字段是只读的。创建 Foo 对象后无法更改它们。因此,任何 Foo 对象的任何使用都是线程安全的。即使您将同一个 Foo 对象赋予 10 个不同的线程;他们将始终看到相同的数据。

类的这个属性称为不变性;您可以通过对 Foo 中的两个字段使用 Final 关键字来使其更加明确。简单地说:如果您可以将所有类设计为不可变的,那么就不用担心线程安全了。

但是,如果 Foo 上有 setter ,使其他人能够在创建 Foo 对象时更改字段;那么“本地”与“现场”确实会产生影响。

关于java - 多线程:将实例和局部变量传递给线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36164937/

相关文章:

c++ - 创建一个跨 MPI 进程保持同步的计数器

c++ - 返回指向在不同线程中更新的 QML 的 C++ 指针

java - 从各种未知来源检索特定对象的模式/设计方法

java - 使用 java.awt.Robot 键入字符串

windows - 在线程中调用 SHGetFileInfo 以避免 UI 卡住

javascript - 如何循环等待多个WebWorker

java - 查找/打印以特定字母开头的特定单词

java - 如何拦截wicket中的页面创建?

java - 等待 JavaFX 应用程序线程完成事件处理?

delphi - 具有 'thread-safe'读/写操作的Delphi数据类型列表?