假设我有一个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()
方法和,而操作进入方法调用,另一个线程调用相同的方法传递不同的{{1 }}。
在这种情况下会发生什么? Java会锁定静态方法吗?
答案 0 :(得分:10)
这里没有问题。每个线程都将使用自己的堆栈,因此不同的s
之间没有冲突点。 Integer.parseInt()
是线程安全的,因为它只使用局部变量。
答案 1 :(得分:3)
除非您添加关键字synchronized
。
请注意,当您锁定静态方法时,您将获取实现该方法的Class对象的Mutex,因此在静态方法上进行同步将阻止其他线程进入任何其他“同步”静态方法。
现在,在您的示例中,您不需要在此特定情况下进行同步。那是因为参数是通过复制传递的;因此,多次调用静态方法将导致参数的多个副本,每个副本都在自己的堆栈帧中。同样,对Integer.parseInt(s)
的同时调用将分别创建自己的堆栈帧,并将s值的副本传递到单独的堆栈帧中。
现在,如果Integer.parseInt(...)以非常糟糕的方式实现(它在parseInt执行期间使用静态非final成员;那么就会有一个值得关注的原因。幸运的是,Java的实现者图书馆是比这更好的程序员。
答案 2 :(得分: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.
}
}
}
但是,它不会将该方法标记为已同步,除非您正在访问可以修改的共享数据,否则不需要同步。
答案 3 :(得分:0)
除非明确指明,否则不应该。此外,在这种情况下,不存在任何线程安全问题,因为“s”是不可变的,也是方法的本地。
答案 4 :(得分:0)
您不需要同步,因为变量 s 是本地的。
只有当多个线程共享资源时才需要担心,例如如果 s 是静态字段,那么你必须考虑多线程。