[concurrency-interest] Double Checked Locking in OpenJDK

Wolfgang Baltes wolfgang.baltes at laposte.net
Mon Aug 13 17:46:06 EDT 2012


Immutability and thread safety should be considered essentially 
orthogonal concepts. However, the final keyword can be useful in both.

Immutability just means that the object cannot be changed after 
instantiation. There are several ways to achieve this, the most obvious 
ones are a) to make a data fields final, and b) not to provide a method 
that changes the values of data fields.

Thread safe publishing means that, when an object reference is shared 
between threads, all threads see the object only in the same state as 
the thread which has last modified (or instantiated) the object. There 
are different ways to accomplish this, the most obvious ones being to 
declare a fields final or volatile. Final provides the guarantee that a 
field can safely be published to other threads after the constructor 
that assigns the value is finished. If there are multiple fields, than 
only those that are marked final are covered by the guarantee. This is 
different from volatile, where instructions - such as writes to non 
volatile fields - that appear in the code before a write to a volatile 
field, are guaranteed to be executed before the first subsequent read of 
that volatile field, no matter in which thread this read instruction 
occurs. In the latter case, a non volatile field which is never modified 
by any method may also appear as immutable and be published in a thread 
safe manner.

Hence, marking a field final makes it immutable and publishable in a 
thread safe manner, if the reference to the object that holds the field 
is published after the constructor is finished.

Wolfgang.


On 2012-08-13 13:20, Ruslan Cheremin wrote:
> Yes, and it is my point -- it's confusing to say "immutable" (which
> form of?), confusing to say "thread safe" (in which multithreaded use
> case it is safe?) and even more confusing to say both "immutable and
> thread-safe" -- because actually there is (==I know) only two ways to
> reach thread-safe immutability in java: "all fields final", or "all
> methods sync-ed, including constructors" -- and the second one is very
> rare.
>
> For me "immutable and thread safe" seems to be equivalent to
> "thread-safe immutable", which, in turn, implies safety for data race
> publication. How can I claim object as "thread safe immutable", if I
> can see in several states in multithreaded env.?
>
>
> 2012/8/13 Yuval Shavit <yshavit at akiban.com>:
>> This class is immutable but not thread-safe absent safe publication:
>>
>> public class MyImmutable {
>>      private long val; // not marked final or volatile
>>      public MyImmutable(long val) {
>>          this.val = val;
>>      }
>>
>>      public int getValue() {
>>          return val;
>>      }
>> }
>>
>> In the absence of safe publication, a thread is allowed to see:
>>
>>      - val's default value (0)
>>      - the value passed to the constructor
>>      - a word tear in which val contains only the high or low word from the
>> value passed to the constructor
>>
>>
>> On Mon, Aug 13, 2012 at 3:39 PM, Ruslan Cheremin <cheremin at gmail.com> wrote:
>>> For me it is confusing: java has only one way to have really immutable
>>> object, and this way also gives you a total thread safety even for
>>> data race based publication. But then docs refer object as "immutable
>>> and thread-safe" -- we still can't assume it to be really thread-safe?
>>>
>>> It's a pity, especially because true immutability gives us some
>>> chances of performance optimization. As in this case -- we do not
>>> really need .path to be volatile here, if we would assume Path to be
>>> truly immutable. volatility here required only for ensuring safe
>>> publishing.
>>>
>>> 2012/8/13 David Holmes <davidcholmes at aapt.net.au>:
>>>> Ruslan Cheremin writes:>
>>>>> But is there a way to define "safe for data race publishing"? I as
>>>>> far, as I remember, "immutable and thread-safe" is standard mantra in
>>>>> JDK javadocs for totally safe objects. j.l.String has same mantra --
>>>>> and it is safe for any way of publishing. Does you mean, I should
>>>>> explicitly add "safe even for publishing via data race" in docs? But I
>>>>> can't remember any such phrase in JDK docs.
>>>> I don't recall anything in the JDK docs that mention being "totally
>>>> safe"
>>>> regardless of publication mechanism. Some classes, eg String, have been
>>>> defined such that they do have that property (for security reasons). In
>>>> general neither "thread-safe" nor "immutable" imply
>>>> safe-for-unsynchronized-publication.
>>>>
>>>> Java Concurrency In Practice (jcip.net) does define additional potential
>>>> annotations, where @Immutable would indeed capture the requirement of
>>>> safe-for-unsynchronized-publication.
>>>>
>>>> David
>>>> -----
>>>>
>>>>> 2012/8/13 David Holmes <davidcholmes at aapt.net.au>:
>>>>>> Ruslan Cheremin writes:
>>>>>>> Well, Path javadoc explicitly says "immutable and safe for
>>>>>>> multithreaded use". Although it is not strictly defined in java what
>>>>>>> exactly means "safe for multithreaded use" -- does it mean safe for
>>>>>>> publishing via data race, among others? -- I suppose, it should be.
>>>>>>> Am
>>>>>>> I wrong here?
>>>>>> "safe for multi-threaded use" does not generally imply that it
>>>>> is safe to
>>>>>> publish instances without synchronization of some form.
>>>>>>
>>>>>> David
>>>>>> -----
>>>>>>
>>>>>>>  From other side, File.toPath javadoc explicitly says what "returned
>>>>>>> instance must be the same for every invocation", so sync block is
>>>>>>> required here for mutual exclusion on initialization phase. Without
>>>>>>> this requirement it is also safe to live without sync block, afaik.
>>>>>>>
>>>>>>> 2012/8/13 David Holmes <davidcholmes at aapt.net.au>:
>>>>>>>> Ruslan Cheremin writes:
>>>>>>>>> First of all, Path is immutable, so DCL is safe here even without
>>>>>>>>> volatile. Volatile here is not required from my point of view.
>>>>>>>> Without the volatile the Path implementation (Path is an
>>>>>>> interface) must be
>>>>>>>> such that an instance of Path can be safely published without
>>>>>>> any additional
>>>>>>>> forms of synchronization. Immutability does not in itself
>>>>>>> ensure that. You
>>>>>>>> would have to examine the actual implementation class.
>>>>>>>>
>>>>>>>> David Holmes
>>>>>>>> ------------
>>>>>>>>
>>>>>>>>>
>>>>>>>>> 2012/8/12 Dmitry Vyazelenko <vyazelenko at yahoo.com>:
>>>>>>>>>> Hi Richard,
>>>>>>>>>>
>>>>>>>>>> The variable "filePath" is volatile, so the double-checked
>>>>>>>>> locking is correct in this case. It would have been a bug
>>>>>>> prior to Java 5.
>>>>>>>>>> Best regards,
>>>>>>>>>>
>>>>>>>>>> Dmitry Vyazelenko
>>>>>>>>>>
>>>>>>>>>> On Aug 12, 2012, at 21:35 , Richard Warburton
>>>>>>>>> <richard.warburton at gmail.com> wrote:
>>>>>>>>>>> Hello,
>>>>>>>>>>>
>>>>>>>>>>> The current implementation of java.io.File::toPath [0]
>>>>> appears to be
>>>>>>>>>>> using the double checked locking pattern:
>>>>>>>>>>>
>>>>>>>>>>>      public Path toPath() {
>>>>>>>>>>>          Path result = filePath;
>>>>>>>>>>>          if (result == null) {
>>>>>>>>>>>              synchronized (this) {
>>>>>>>>>>>                  result = filePath;
>>>>>>>>>>>                  if (result == null) {
>>>>>>>>>>>                      result =
>>>>> FileSystems.getDefault().getPath(path);
>>>>>>>>>>>                      filePath = result;
>>>>>>>>>>>                  }
>>>>>>>>>>>              }
>>>>>>>>>>>          }
>>>>>>>>>>>          return result;
>>>>>>>>>>>      }
>>>>>>>>>>>
>>>>>>>>>>> I was going to report the bug, but I'm a little uncertain of
>>>>>>>>>>> the
>>>>>>>>>>> interaction between the local variable 'result' and DCL
>>>>> since I've
>>>>>>>>>>> previously only seen the checking condition on the shared
>>>>>>>>>>> field
>>>>>>>>>>> itself.  Can someone here either confirm that its a bug or
>>>>>>> explain how
>>>>>>>>>>> the 'result' variable is fixing things?
>>>>>>>>>>>
>>>>>>>>>>> regards,
>>>>>>>>>>>
>>>>>>>>>>>   Richard
>>>>>>>>>>>
>>>>>>>>>>> [0] See the end of
>>>>>>>>>>>
>>>>>>>>> hg.openjdk.java.net/jdk8/jdk8/jdk/file/da8649489aff/src/share/clas
>>>>>>>>> ses/java/io/File.java
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Concurrency-interest mailing list
>>>>>>>>>>> Concurrency-interest at cs.oswego.edu
>>>>>>>>>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> Concurrency-interest mailing list
>>>>>>>>>> Concurrency-interest at cs.oswego.edu
>>>>>>>>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>>>>>> _______________________________________________
>>>>>>>>> Concurrency-interest mailing list
>>>>>>>>> Concurrency-interest at cs.oswego.edu
>>>>>>>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>>>>>>
>>> _______________________________________________
>>> Concurrency-interest mailing list
>>> Concurrency-interest at cs.oswego.edu
>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>



More information about the Concurrency-interest mailing list