2011-01-22 52 views

回答

8

如果你的方法只对参数和本地定义的(而不是类成员)变量进行操作,那么需要担心的是零同步问题。

但是......

这意味着你用必须生活和你的方法的范围内死亡只有任何可变引用类型。 (不可变的引用类型是不是这里有问题。)例如,这是没有问题的:

int doSomething(int myParameter) 
{ 
    MyObject working_set = new MyObject(); 
    interim = working_set.doSomethingElse(myParameter); 
    return working_set.doSomethingElseAgain(interim); 
} 

一个MyObject实例你的方法中创建的,做所有的工作在你的方法,并咳血,等待当你退出你的方法时,由GC来剔除。

此,在另一方面,可能是一个问题:

int doSomething(int myParameter) 
{ 
    MyObject working_set = new MyObject(); 
    interim = working_set.doSomethingElse(myParameter); 
    another_interim = doSomethingSneaky(working_set); 
    return working_set.doSomethingElseAgain(another_interim); 
} 

除非你肯定知道发生了什么事在doSomethingSneaky(),您可能需要同步的地方。具体而言,您可能必须在working_set上执行同步操作,因为doSomethingSneaky()可能会存储对本地working_set对象的引用,并在您仍在执行方法或working_set方法中的操作时将该引用传递给另一个线程。在这里你必须更加防守。

当然,如果您只使用原始类型,即使调用其他方法,传递这些值也不会成为问题。

+0

“任何引用类型”应该可以是“任何_mutable_引用类型”...不可变对象不是问题。 – ColinD 2011-01-22 20:08:26

0

您不需要担心局部变量。但是实例变量是值得关注的。

4

是否只使用局部变量的方法,不会遇到任何线程问题?

在一个非常简单的道理没错,但让是明确的 - 我想如果这是唯一真正:

  • 这种方法只使用局部变量是原语或引用可变的情况下,可以不否则通过任何其他方式访问该方法之外。

  • 这样的方法只调用线程安全的方法。

的一些方法,这些规则可能被侵犯:

  • 的局部变量可以被初始化为指向一个对象,这也是该方法外部访问。例如,局部变量可能指向单例(Foo bar = Foo.getSingleton())。

  • 如果将实例作为参数传递给保存对实例的引用的外部方法,则由本地变量持有的本地实例可能会“泄漏”。

  • 没有实例变量并且只有一个没有局部变量的方法的类仍然可以调用另一个不是线程安全的类的静态方法。

1

该问题是非常通用的,所以请不要指望我的答案有任何特异性。

1_我们需要比静态方法更小心,而不是说实例方法。

2_ @Justmycorrectopinion是正确的,但他描述的一些术语需要更详细地阐述为完美。 (即使静态方法只适用于局部变量,仍然存在竞态条件的可能性。)

3_对于我来说,有一些简单的规则可以帮助我分析线程安全性。

了解封装在其中的每个组件是否可共享。所以最简单的解决方案是减少所有变量的范围,并且如果绝对必要的话只增加范围,并且如果组件在对象上执行突变,则它通常不是线程安全的。

4_使用工具支持对线程安全执行静态代码分析。 (Idea有checkthread插件)。

5_永远不要使用静态方法来执行对象变异。如果调用静态变量导致对象变异,那么开发人员只是绕开OOPS。

6_始终记录线程安全性。记住一些方法在开发时可能不需要同步,但可以非常容易地使线程安全。

7_最后但可能是我最重要的一点,请确保大部分对象是不可变的。根据我的经验,大多数时候,我从来没有必须让很多对象变化。 (在极少数情况下,当对象状态需要更改时,防御性复制/新建对象创建几乎总是更好。)

相关问题