This reminds me very much of the discussion about the
'double checked locking' pattern. Although there was the
claim that it is broken it was a highly theoretical discussion.
As far as I know no one ever proofed that claim on a modern
jvm (> 1.1).
For example a simple question has never been answered: What kind of
exception occurs if an "not fully instantiated" class is called?

I severly doubt that any test scenario will proof the
synchronization problem. And if any user will ever have this
problem there is an easy work around: eager load the service
and call some method on it.

Achim

Am Thu, 08 Jun 2006 20:06:12 +0200 schrieb Howard Lewis Ship <[EMAIL PROTECTED]>:

The discussion at:
http://howardlewisship.com/blog/2006/06/whoa-spring-doesnt-lazily-instantiate_05.html

has pointed out that, quite possibly, HiveMind has synchronization problems
w.r.t. instantiating services.

I'm not completely buying it. Looking at the code paths, it seems unlikely
to me that the compiler would have much opportunity to inline things.

Insidethe inner proxy (generated by SingletonServiceModel) we see the
following code:

private final synchronized MyServiceInterface _service()
{
  if (_service == null)
  {
    _service = (MyServiceInterface )
_serviceModel.getActualServiceImplementation();  // 1

_deferredProxy._setInner(_service);
// 2
  }

  return _service;
}

The memory model for Java is a tricky thing in concurrent code.

The first line of code (// 1) may not completely execute before (// 2) does. That leaves a tiny window where _service is not fully instantiated and yet
is exposed (via the OuterProxy, aka _deferredProxy) to some other thread.
Further, the nature of these two statements means that //2 can't happen
before //1, just in parallel.  It's a pretty damn tight window.

Personally, I don't see it.  If (// 1) was just creating a new instance,
there might be something. However, getActualServiceImplementation() does a
lot of work, much of it delegated to other objects. The secondary objects
(service and interceptor factories) are hidden behind interfaces, interfaces
with multiple implementations (and therefore, not likely to be inlined by
the magic of Hotspot). The window shrinks from merely remotely possible to
zero.

Further, the scenarios necessary for even the remotely possible window are
not completely likely. If multiple threads all hit _service() at the same
time, they will be serialized by the synchronized lock on the method. What's
necessary is that, while //1 and //2 are both running, yet another thread
arrives inside the OuterProxy and sees the full service implementation (via
//2) before the initialization code (// 1) finished executing.

I'd love for every bit of code I write to be provably correct under any
circumstances. For this to be an actual concern, we'd need the intersection
of many different unlikely scenarios to line up:  the threads arriving
inside the OuterProxy and InnerProxy at just the right times (highly
unlikely) along with Hotspot reording the code (distributed across at least
a dozen different classes) so that //2 occurs before //1 completes.
LIkelyhood falls close enough to zero to not be an issue.

I really like the fact that, once the service implementation is fully
instantiated, the inner proxy goes away, and the outer proxy can delegate to
the service implementation without needing any synchronization.




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to