![](/img/trans.png)
[英]In Java, do methods that don't use static or class variables need to be synchronized?
[英]Java: Do all static methods need to be synchronized?
我有一个朋友说,所有静态方法都应该在Java Web应用程序的上下文中synchronized
。 真的吗? 我已经阅读了很多关于此的堆栈溢出页面。 我所相信的是,如果你有以下情况,你只需要同步:
基于此,我认为静态成员应该是同步的,而不是静态方法。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadTest {
static String staticString = "";
// This static method is safe b/c it only uses local data.
// It does not use any shared mutable data.
// It even uses a string builder.
static String safeStaticMethod(String in) {
// This also proves that StringBuilder is safe
// When used locally by a thread.
StringBuilder sb = new StringBuilder();
sb.append("Hello: ");
sb.append(in);
return sb.toString();
}
// This static method is not safe b/c it updates and reads
// shared mutable data among threads.
// Adding synchronized will make this safe.
static String unsafeStaticMethod(String in) {
staticString = in;
StringBuffer sb = new StringBuffer();
sb.append("Hello: ");
sb.append(staticString);
return sb.toString();
}
public static void main(String[] args) {
ThreadTest test = new ThreadTest();
test.staticMethodWithLocalData();
test.staticMethodWithStaticData();
}
public void staticMethodWithLocalData() {
ExecutorService executor = Executors.newFixedThreadPool(2);
final int iterations = 100000;
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!safeStaticMethod("Thread1").equals("Hello: Thread1")) {
System.out.println("safeStaticMethod at " + index);
}
}
}
});
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!safeStaticMethod("Thread2").equals("Hello: Thread2")) {
System.out.println("safeStaticMethod at " + index);
}
}
}
});
}
public void staticMethodWithStaticData() {
ExecutorService executor = Executors.newFixedThreadPool(2);
final int iterations = 100000;
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!unsafeStaticMethod("Thread1").equals("Hello: Thread1")) {
System.out.println("unsafeStaticMethod at " + index);
}
}
}
});
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!unsafeStaticMethod("Thread2").equals("Hello: Thread2")) {
System.out.println("unsafeStaticMethod at " + index);
}
}
}
});
}
}
这段代码证明了这一点吗?
编辑:这只是我破解的一些一次性代码来证明这一点。
不,并非所有静态方法都需要同步。 就我所见,你的清单基本上已经完成。 静态方法时要特别小心
我认为不用说1(首先有线程)是一个先决条件,因为没有线程synchronize
是没有意义的。
我从来没有听过2,所以我不确定这是否是一个考虑因素。
不,这不是真的,我相信这将是有害的。 并非每个应用程序都需要并发,即使在需要并发的应用程序中,也不是每个代码都必须。
作为更多证据,请查看String的来源。 那里有很多静态方法,但我只能找到一个同步方法,而且那个方法甚至不是静态的。
静态方法几乎不应该在webapp中同步。 除非你100%确定将会使用该应用程序的唯一人员是你的3人会计团队,并且如果它在全公司范围内起飞并且所有的突然研究几乎停止,那么他们愿意变红。
创建全局,阻塞,共享资源是可扩展性的完全失败! 如果您最终需要集群应用程序服务器,这也会让您感到很头疼,并可能将您锁定为Terracotta样式解决方案。
在Web应用程序中(比如使用servlet / JSP的一个构建),您应该始终避免使方法同步,因为它挑战了多线程可访问性的整个原则。 在适当的位置,始终尝试在synchronized块中放置唯一需要逐个访问的必要代码。
一点也不。 大多数情况下,我遇到的静态方法不会修改任何静态变量,因此它们不需要同步 。
为了简单理解,
//sample static util method to get string in upper case
public static String getName(String name){
return a.toUpperCase();
}
上面的方法可以被1000个线程调用,但它将是线程安全的,因为该方法只需要一个参数 - 字符串名称 ,并且来自线程堆栈。 它不是线程之间的共享数据。
想一想,如果所有静态方法都是同步的,那么Web应用程序应该非常慢并且难以使用。 只要一个线程试图访问该方法,我们就会有类级锁。
JDK提供的API中有很多静态方法。 如果所有这些都是同步的,我很确定我们不会使用JAVA。
在您的情况下, 静态变量 (类级变量)由静态方法修改。 是的,如果创建了多个线程并且它们将访问静态方法,则可能存在线程干扰。 它不是线程安全的,因为它们之间存在共享数据 。
大多数情况下,静态方法是实用函数,具体取决于传递给它们的参数。
请注意,如果非同步静态方法不修改静态类变量,则它们是线程安全的 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.