问题 Java中的方法参数是否安全?


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 正在线程之间共享
  • 如果每个Thread都有自己的副本 someObject 

9248
2017-08-31 11:28


起源

不,你不能这么说。 - bmargulies


答案:


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


10
2017-08-31 11:30



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


是的,但仅限于两种情况

  • 如果你传递的每个物体 o 参数是 一成不变
  • 如果您的代码保证最多有一个线程处理引用的对象 o

除此以外 - 没有,因为对象的内部状态可以由多个线程同时更改。


1
2017-08-31 11:33





如果在多个线程中调用相同的方法,并将相同的对象传递给它,则该对象绝对是  安全。


1
2017-08-31 11:33





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

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

只有在同一个对象上调用它才会生效。


1
2017-08-31 11:38



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


这样对待它。

如果您的线程不共享任何公共资源,那么就不可能出现并发问题。 尽管我们可以从您提供的信息中分辨出来,但这里唯一可以分享的是 someObject。如果它本身是线程安全的,或者是为每个线程复制的,那么除非代码是一般的线程安全的,否则除非有其他共享资源。


0
2017-08-31 12:07





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

编辑

此示例中的LocalObject实例不从方法返回,也不传递给可从外部访问的任何其他对象 sharedMethod() 方法。

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

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

当然,唯一的例外是,如果使用Object调用其中一个方法 o 作为参数,存储Object o 实例,允许从其他线程访问它。


0
2017-08-31 11:49