我有一个关于Java中多线程方法调用的问题。假设我们有一个单例对象,其类声明如下:
public class SomeClass {
public void someMethod(SomeValueObject object) {
if (object.condition1) {
...
}
if (object.condition2) {
...
}
if (object.condition3) {
...
}
}
}
我想知道这个单例对象是否被同时访问并且someMethod是否使用不同的SomeValueObject实例调用,是否有可能一些随机线程更改 object 的引用另一个线程的方法调用和搞砸事情?那么在方法范围内创建的字段呢? 我不知道的是,是否为调用该方法的每个线程创建了单独的Method上下文,或者对于调用它的所有线程,Method上下文是否相同?如果是后一种情况,我想我需要 synchronized 关键字来保证线程安全,或者为每个线程使用不同的SomeClass实例(如果我需要更快的内存优化执行) )。你能帮我解释一下吗?
P.S。谢谢你们的所有答案!
答案 0 :(得分:13)
如果一切都是本地的,那么您的方法就是线程安全的。每个线程在堆栈上都有自己的对象参数,它们不会相互干扰。
如果两个线程使用与参数相同的对象调用此方法,或者如果其中两个对象共享某个状态,则可能会出现并发问题,但这不是单例的问题。这是共享状态的问题,必须正确同步。
良好的经验法则:无状态对象是线程安全的。具有不可变状态的对象是线程安全的。如果具有可变状态的对象未正确同步对共享状态的访问,则该对象不是线程安全的。
答案 1 :(得分:8)
不,线程将无法更改其他线程的局部变量。
在方法的范围[局部变量]中创建的所有变量 - 包括参数都在特定线程的堆栈上分配,因此不会在两个线程之间共享。
然而 - 所有类的字段都是不安全的,如果一个线程更改它们 - 它将反映在所有类中。
答案 2 :(得分:3)
每个线程都有自己的执行堆栈。该内存区域包含所有局部变量和方法参数。当两个线程同时执行相同的代码时,两者都使用不同的堆栈。
因此,不可能通过不同的线程更改方法参数或局部变量的值。
答案 3 :(得分:3)
方法本质上是一段代码。当一组线程调用一个方法时,每个线程的堆栈上都存在该方法的不同副本,因此局部变量不会相互干扰。
如果另外,每个线程的所有参数都是不同的,那么就有完美的隔离,除非你的方法在其代码中运行其他共享数据。
答案 4 :(得分:3)
其他人说的话。虽然要挑选:在java中,只有本地原始变量和参数(int,long,boolean等)在堆栈上分配,所有其他对象都在堆上分配,只有引用存储在堆栈中。但是其他人说每次调用该方法都会看到自己的局部变量副本。
请注意,作为参数传递的对象(与基元相对)不一定是每次调用唯一的,因为objet参数只是引用。因此,如果将相同的输入对象传递给方法两次,则两者都将在同一输入上运行。