我们将举几个例子来看静态方法是否线程安全。
例子1:
public static String concat (String st1, String str2) {
return str1 + str2
}
现在上面的方法是线程安全的。
现在我们来看一个不安全的例子。
例子2:
public static void concat(StringBuilder result, StringBuilder sb, StringBuilder sb1) {
result.append(sb);
result.append(sb1);
}
如果你看到两种方法都非常原始,但其中一个是线程安全的,另一个则不是。为什么?它们有什么区别?
工具类中的静态方法是否容易出现非线程安全问题?很多问题,对吧?
现在一切都取决于你如何实现方法和你在方法中使用哪种类型的对象。你是否使用线程安全的对象?这些对象/类是否可变?
如果你看Example 1,concat方法的参数是String类型的,它们是不可变的并按值传递,因此该方法完全线程安全。
现在在Example 2中,参数是StringBuilder类型的,它们是可变的,因此其他线程可以更改StringBuilder的值,这使得该方法潜在地不是线程安全的。
但这并不是完全正确的。如果您在本地变量中调用此实用程序方法,则永远不会遇到与线程安全相关的任何问题。因为每个线程都使用自己的本地变量副本,因此您永远不会遇到任何线程安全问题。但这超出了上述静态方法的范围。它取决于调用函数/程序。
现在,在实用程序类中使用静态方法是一种正常的做法。那么我们该如何避免它呢?如果您看Example 2,我正在修改第一个参数。现在,如果您想使此方法真正线程安全,则可以做一件简单的事情。要么使用不可变变量/对象,要么不要更改/修改任何方法参数。
在Example 2中,我们已经使用了可变的StringBuilder,所以您可以更改实现方式来使静态方法线程安全,如下所示:
public static String concat1(StringBuilder sb, StringBuilder sb1) {
StringBuilder result = new StringBuilder();
result.append(sb);
result.append(sb1);
return result.toString();
}
再次回归基础,永远记住,如果您正在使用不可变对象和局部变量,则与线程安全问题相差甚远。
来自文章(https://nikhilsidhaye.wordpress.com/2016/07/29/is-static-method-in-util-class-threadsafe/)感谢 Nikhil Sidhaye 提供这篇简单的文章。
synchronized
吗? - Andrew Logvinov