'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:
- make an assignment to a volatile field as the last statement in the constructor (this will make sure that write to
$callSiteArrayin constructor is applied) - wrap every use of any non volatile variable into the
synchronizedmethod.
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 |
|---|
