我怀疑将实例和局部变量作为参数传递给线程。
让我向您展示一个简短的例子:
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();
}
}
这只是一个启动两个线程的愚蠢程序:一个将实例变量作为参数传递给线程,另一个传递一个局部变量。之后,两个线程都将传递的参数中的内容写入控制台。
在局部变量的情况下,我确定它的行为是线程安全的。在第二种情况下,我认为它不会,因为可能缓存该变量。你怎么看待这件事?我错了吗?
答案 0 :(得分:0)
这很简单:如果可以通过线程更改信息,则总是要担心线程安全。
重要的是:能够改变。
在您的示例中,Foo的字段是只读的。创建Foo对象后无法更改它们。因此,任何Foo对象的使用都是线程安全的。即使你给10个不同的线程提供相同的Foo对象;他们总会看到相同的数据。
一个类的这个属性称为不变性;你可以通过对Foo中的两个字段使用final关键字来使其更加明确。简单来说:如果你可以设计所有的类都是不可变的,那么就不用担心线程的安全性了。
但是,如果在Foo上有固定器,则允许其他人在创建Foo对象时更改字段;然后“本地”与“场”确实会产生影响。