Simple method for adding Thread safe?

Having this simple class, with an add method:

class A {
   public Integer add (int a, int b){
     return a+b;
   }
}

      

is it thread safe or not ..? this looks safe to me, but most poeples answer no, can anyone explain why?

+3


source to share


3 answers


It is completely thread safe since all variables are local.



+2


source


Thread safety should only be concerned when you have some kind of sharing facility and you change that without any locks or synchronization, i.e. you are modifying a shared variable (class level variable), then you have to worry about thread safety.
There is no thread safety issue here.
And in this particular case, each variable is local and that place will not be shared by threads, since each function call will have them on a separate allocation on the stack along with their local variables , you shouldn't worry anyway :)



+3


source


This method is not actually thread safe, but in order to understand why it is needed, you need to know a little about the internals of the class Integer

. Let's take a look at some code that gives the same bytecode:

class A {
   public Integer add (int a, int b){
     // auto boxing hidden in OP implementation
     return Integer.valueOf(a+b);
   }
}

      

Small enough values Integer

are cached and viewed in the array. Using reflection, you can access this array and modify its elements. These changes are not synchronized , so if you change these items from a different thread, the result of your method may also change.

The following code should demonstrate the problem on most Java virtual machines: There is a race condition in your method. Most of the time it will print 4 and 5 seconds:

import java.lang.reflect.Field;

class A {

    public Integer add(int a, int b) {
        return a + b;
    }

    private static volatile boolean cont = true;

    public static void main(String[] args) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InterruptedException {
        final A a = new A();

        new Thread(() -> {
            while(cont) {
                for (int i = 0; i < 100; i++) {
                    // print result of add method
                    System.out.println(a.add(2,2));
                }
            }
        }).start();

        // give other thread time to start
        Thread.sleep(1);

        // mess around with the internals of Integer
        Class cache = Integer.class.getDeclaredClasses()[0];
        Field c = cache.getDeclaredField("cache");
        c.setAccessible(true);
        Integer[] array = (Integer[]) c.get(cache);
        array[132] = array[133];

        cont = false;
    }
}

      

Most of the time, however, no one encounters the internals Integer

. If the array in the class Integer

never changes, the object-wrapped values Integer

returned by your method will always be correct, since the shared state used Integer.valueOf

never changes. Therefore, in this case, it will be thread safe.

+2


source







All Articles