Java:是否需要同步所有静态方法?

Jes*_*ess 7 java synchronization servlets thread-safety

我有一个朋友说所有静态方法都应该synchronized在Java Web应用程序的上下文中.真的吗?我已经阅读了很多关于此的堆栈溢出页面.我所相信的是,如果你有以下情况,你只需要同步:

  1. 多个线程(如在带有线程池的Sevlet容器中)
  2. 单个ClassLoader
  3. 线程之间的共享数据,无论是会话数据还是静态成员数据.
  4. 共享数据必须是可变的.只读数据可以共享.

基于此,我认为静态成员应该是同步的,而不是静态方法.

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);
                    }
                }
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码证明了这一点吗?

编辑:这只是我破解的一些一次性代码来证明这一点.

hvg*_*des 10

不,并非所有静态方法都需要同步.就我所见,你的清单基本上已经完成.静态方法时要特别小心

  1. 访问可变的静态成员,或
  2. 获取传递对可修改对象的引用.

我认为不用说1(首先有线程)是一个先决条件,因为没有线程synchronize没有任何意义.

我从来没有听过2,所以我不确定这是否是一个考虑因素.