Java中静态方法的同步问题

3
假设我有一个Utility类:
public class Utility {

    private Utility() {} //Don't worry, just doing this as guarantee.

    public static int stringToInt(String s) {
        return Integer.parseInt(s);
    }
};

现在,假设在一个多线程应用程序中,一个线程调用Utility.stringToInt()方法,同时,另一个线程调用相同的方法,并传递不同的s参数。

在这种情况下会发生什么?Java会锁定静态方法吗?


这个问题的原因是我们收到具有不同规则和值的XML文件(而且XML没有固定的定义,同时可能会有多个调用相同服务的情况,这些调用同时传递这些XML)。 - Buhake Sindi
5个回答

10

这里没有问题。每个线程将使用自己的堆栈,因此不会发生不同 s 之间的冲突。而且 Integer.parseInt() 是线程安全的,因为它仅使用本地变量。


我不担心Integer.parseInt(),我担心调用结果带来意外的结果。 - Buhake Sindi
静态方法只是在其自己的堆栈上操作的一系列操作码。堆栈不重叠,因此您可以放心使用。 - Alex Gitelman
@The Elite..:正如之前所说,所有的线程都使用自己的堆栈。你知道,局部变量存在于堆栈中,而实例/类变量则驻留在堆中。 - Adeel Ansari

3

Java不会锁定静态方法,除非您添加关键字synchronized

请注意,当您锁定静态方法时,您会抓取实现该方法的类对象的Mutex,因此在静态方法上同步将防止其他线程进入任何其他“同步”静态方法。

现在,在您的示例中,在这种特殊情况下,您不需要同步。那是因为参数是通过副本传递的; 因此,对静态方法的多次调用将导致多个参数副本,每个副本都在自己的堆栈帧中。同样,对Integer.parseInt(s)的同时调用将创建它们自己的堆栈帧,其中包含将s的值传递到单独堆栈帧中的副本。

如果Integer.parseInt(...)以非常糟糕的方式实现(在parseInt执行期间使用静态非最终成员),那么就有很大的担忧。幸运的是,Java库的实现者比那更好。


1
在你提供的例子中,线程之间没有共享数据,并且也没有被修改的数据。(只有两者都存在才会出现线程问题)

你可以写

public enum Utility {
    ; // no instances

    public synchronized static int stringToInt(String s) {
        // does something which needs to be synchronised.
    }
}

这实际上与之相同

public enum Utility {
    ; // no instances

    public static int stringToInt(String s) {
        synchronized(Utility.class) {
            // does something which needs to be synchronised.
        }
    }
}

然而,它不会为您标记方法为同步,并且除非您正在访问可以被修改的共享数据,否则您不需要同步。


0

除非明确指定,否则不应该返回。此外,在这种情况下,由于“s”是不可变的并且也是局部方法,所以不会有任何线程安全问题。


0

在这里,您不需要同步,因为变量s是本地的。

只有当多个线程共享资源时,例如如果s是静态字段,那么您才需要考虑多线程问题。


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