Java中的方法参数是否线程安全?

15
Class Shared{    
     public void sharedMethod(Object o){
          //does something to Object
     }     
}

//this is how threads call the shared method
run(){
     sharedInstance.sharedMethod(someObject);
}

现在把 o 作为参数传递给该方法。而且同一个方法被多个线程同时调用。我们能否安全地说这段代码是线程安全的?

有两种情况:

  • 如果 someObject 在线程之间共享
  • 如果每个线程都有自己的 someObject 副本

不,你不能这么说。 - bmargulies
6个回答

17

不可以这么说。方法参数是线程本地的,这意味着每个线程都有自己的o引用变量的副本。但是,如果您从多个线程使用相同的对象调用此方法,则参数将在它们之间共享(请记住,Java是按值传递)。在这种情况下,您需要提供明确的同步以避免问题。


你有两个不同的“引用”副本(一个在调用方法中,一个在被调用方法中 - 因为是按值传递),而不是“对象”本身。在一个方法中更改“引用”不会影响另一个方法(例如,在被调用方法中o=null不会使调用方法中的o为空),但更改它们所引用的“对象”(在这种情况下,两者都指向同一个对象)对另一个可见。因此,两个线程都在同一个对象上工作,因此不是线程安全的。 - user104309

4

是的,但只有在两种情况下

  • 如果您在o参数中传递的每个对象都是不可变的
  • 如果您的代码保证最多有一个线程在引用o的对象上工作。

否则 - 不行,因为多个线程同时可以更改对象的内部状态。


2

当您创建一个线程时,它将创建自己的堆栈(方法和局部变量)。

两个线程将有两个堆栈,而一个线程永远不会与任何其他线程共享其堆栈。

除非您在同一对象上调用此函数,否则它不会产生影响。


4
@Narenda在谈论对象参数(传递引用),因此它不是线程安全的。 - camposer

1
如果在多个线程中调用同一方法,并传递相同的对象,则该对象绝对不安全。

0

本地变量存储在每个线程自己的堆栈中。这意味着本地变量永远不会在线程之间共享。这也意味着所有本地基本变量都是线程安全的。

编辑

在这个例子中,LocalObject实例既没有从方法中返回,也没有传递给从sharedMethod()方法外部可访问的任何其他对象。

执行sharedMethod()方法的每个线程将使用自己的Object o作为参数。

因此,整个sharedMethod()方法似乎是线程安全的。

唯一的例外是,如果使用Object o作为参数调用的方法之一以允许其他线程访问的方式存储了Object o实例。


0

这样处理。

如果您的线程不共享任何公共资源,则不可能出现并发问题。根据您提供的信息,我们可以得出的唯一共享对象是someObject。如果它本身是线程安全的,或者为每个线程复制了一个副本,则您的代码通常是线程安全的,除非存在其他共享资源。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接