'How to design a thread safe class in groovy

In a nutshell the question is how to create a thread safe class in groovy given that compiler generates fields like $callSiteArray which is static, lazy initialized and not synchronized?

Here is an example of the class in java:

class A {
  private final B immutableField;
  private volatile C mutableField;
  ...
}

In this example immutableField will be set in a constructor and will be visible to other threads as guaranteed by JMM for final fields initialized in a constructor. mutableField may be modified after instance creation and that change will also visible to other threads due to volatile modifier.

If I define the same class in groovy there is a problem because groovy compiler generates the code like this when I try to invoke some method on say immutableField:

class A {

   public A(...) {
      CallSite[] var3 = $getCallSiteArray();
      super();
      // usage of var3
   }

   ...

   public void someMethod(D arg) {
      CallSite[] var2 = $getCallSiteArray();
      var2[3].call(this.immutableField, arg); 
   }

   // $FF: synthetic field
   private static SoftReference $callSiteArray;

   // $FF: synthetic method
   private static void $createCallSiteArray_1(String[] var0) {
      var0[0] = "<$constructor$>";
      var0[1] = "empty";
      ...
   }

   // $FF: synthetic method
   private static CallSiteArray $createCallSiteArray() {
      String[] var0 = new String[138];
      $createCallSiteArray_1(var0);
      return new CallSiteArray(A.class, var0);
   }

   // $FF: synthetic method
   private static CallSite[] $getCallSiteArray() {
      CallSiteArray var0;
      if ($callSiteArray == null || (var0 = (CallSiteArray)$callSiteArray.get()) == null) 
   {
         var0 = $createCallSiteArray();
         $callSiteArray = new SoftReference(var0);
      }

      return var0.array;
   }
}

The problem as one might see is that write/read access to $callSiteArray is not synchronized and non constructing threads might never see the correct value.

One option to overcome this as I can see is to:

  1. make an assignment to a volatile field as the last statement in the constructor (this will make sure that write to $callSiteArray in constructor is applied)
  2. wrap every use of any non volatile variable into the synchronized method.

But this seems to be an overkill and there should be a better way that I most probably missing.

So the question if there are better options to design a thread safe groovy class?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source