Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Do all static methods need to be synchronized?

I have a friend who said that all static methods should be synchronized in the context of a Java web application. Is that true? I have read many other stack overflow pages regarding this. What I have come to believe is that you only need to synchronize if you have:

  1. Multiple Threads (As in a Sevlet Container with a thread pool)
  2. Single ClassLoader
  3. Shared data between threads, whether it is Session data or static member data.
  4. Shared data must be mutable. Read only data is ok to share.

Based on this I think that static members should be synchronized, but not static methods.

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);
                    }
                }
            }
        });
    }
}

Does this code prove the point?

EDIT: This is only some throwaway code I hacked up to prove the point.

like image 575
Jess Avatar asked Feb 13 '13 20:02

Jess


People also ask

Do static methods need to be synchronized?

If it's not using any shared state (e.g. it's really just computing something based on its parameters) then it doesn't need to be synchronized at all.

Can static methods be synchronized in java?

static methods can be synchronized. But you have one lock per class. when the java class is loaded coresponding java.

Can a static method be synchronized yes or no?

A static method cannot be synchronized.

What is the difference between static synchronized and synchronized methods?

When synchronizing a non static method, the monitor belongs to the instance. When synchronizing on a static method , the monitor belongs to the class. In case of non-static synchronized method memory is allocated multiple time whenever method is calling.


1 Answers

No, not all static methods need to be synchronized. Your list is basically complete as far as I can see. Be particularly careful when the static method either

  1. accesses a static member that is mutable, or
  2. gets passed a reference to an object that can be modified.

I think it goes without saying that 1 (having threads in the first place) is a precondition, since without threads synchronize makes no sense.

I've never heard 2, so I don't know for sure if it's a consideration.

like image 142
hvgotcodes Avatar answered Sep 27 '22 16:09

hvgotcodes