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

时间:2016-03-22 20:50:11

标签: 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();
}

}

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

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

1 个答案:

答案 0 :(得分:0)

这很简单:如果可以通过线程更改信息,则总是要担心线程安全。

重要的是:能够改变。

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

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

但是,如果在Foo上有固定器,则允许其他人在创建Foo对象时更改字段;然后“本地”与“场”确实会产生影响。