tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brian Goetz <>
Subject Re: FW: Thread-safety
Date Sat, 27 Jan 2001 02:14:40 GMT

>This is a truly fascinating thread of discussion.  However, from reading the
>article _The "Double-Checked Locking is Broken" Declaration_
>It seems to me that the following code is thread safe.
>if (_jspx_inited == false) {
>     synchronized (this) {
>         if (_jspx_inited == false) {
>             _jspx_init();
>             _jspx_inited = true;
>         }
>     }

This depends on a lot of things.  In particular, it depends on whether 
_jspx_init() creates any objects as a side-effect.  If it does, then this 
is just another broken attempt to fix the double-checked lock 
problem.  (The memory-operation reordering thing is just more complicated 
than it looks.)

Not only can a compiler reorder instructions within a synchronized block 
(and may also move instructions from outside the block into the block, and 
then reorder), but the memory system can make it appear that instructions 
are executed out of order unless BOTH threads synchronize on the SAME lock.

If _jspx_init() were to create an object and assign a reference to it 
somewhere, then you could still obtain a reference to a partially 
constructed object just like with double-checked-locking.

Assuming jspx_init() might create an object (what else would an init() 
routine do?), the problem is that your initial reference of jspx_inited is 
unsynchronized.  Supposed thread A is inside the synchronized 
block.  Thread B is about to execute "if (_jspx_inited == false).  The 
compiler/cache/memory CAN make it appear to thread B that jspx_inited has 
been set to true before all the instructions corresponding to jspx_init() 
have executed.

>In the _jspx_inited case above the only requirement is that compiler can't
>rewrite the code into the equivalent of
>             _jspx_inited = true;
>             _jspx_init();
>Such a re-ordering seems illegal to me (what if jspx_init() uses the value
>of _jspx_inited?).

It might seem illegal, but it isn't.  They could be executed in the 
expected order on one processor, but the memory write corresponding to 
jspx_inited might become visible to thread B before the memory writes 
generated by jspx_init(), unless the reference to jspx_inited is inside a 
synchronized, which it isn't.

But even ignoring memory-system reordering (which you can't) your intuition 
is still incorrect.  The init() can be inlined, and instructions can be 
arbitrarily reordered as long as the compiler/JVM knows that it is not 
violating dataflow assumptions (one instruction requires the result of 
another) and that the intervening instructions won't throw an exception.

>If, however, it is legal reordering then the example of
>a "correct" double-check mechanism for 32-bit primitive values should work
>here.  It would look something like
>boolean tmpInited = _jspx_inited;
>if (tmpInited == false) {
>     synchronized (this) {
>         if (tmpInited == false) {
>             tmpInited = _jspx_init();  // NOTE:  _jspx_init() needs to
>return true
>             _jspx_inited = tmpInited;
>         }
>     }

Still doesn't fix the problem.  jspx_init() can be inlined.  Since the 
return value (true) doesn't depend on other things done by jspx_init(), 
jspx_inited can be set to true (or appear to be so from another thread) 
before all the operations of jspx_init() are finished.

What if jspx_init() is defined like this:

public boolean jspx_init() {
   foo = InitSomething();
   return true;

You've still not created a strong enough dataflow requirement to force the 
compiler to initialize foo before assigning jspx_inited.  And even if you 
had, there'd still be the problem of the appearance of reordering because 
of caching.  The only cure for that is synchronization.

If jspx_init() creates objects or sets any externally accessible value 
other than its return value, then you can't make an end-run around the DCL 
problem this way.

Brian Goetz
Quiotix Corporation           Tel: 650-843-1300            Fax: 650-324-8032

View raw message