Double-checked locking not working - why?

66 Views Asked by At

We are working in an OSGi context and are getting instances of our services via this idiom which includes double-checked locking:

  private volatile ServiceTracker<IMyService, IMyService> serviceTrackerField = null;

  public IMyService getMyService()
  {
    // double-checked locking
    ServiceTracker<IMyService, IMyService> localTracker = this.serviceTrackerField;
    if (localTracker == null)
    {
      synchronized (this)   
      {
        localTracker = this.serviceTrackerField;
        if (localTracker == null)
        {
          localTracker = new ServiceTracker<>(getBundle().getBundleContext(), IMyService.class, null);
          localTracker.open();
          System.out.println("TRACKER = " + localTracker); // X
          this.serviceTrackerField = localTracker;
        }
      }
    }
    return serviceTracker.waitForService(MY_WAIT_TIMEOUT);
  }

I thought I had understood the basic principles (copy to local, use volatile to guarantee order), but still it can happen that the print in line X prints two different instances of the service tracker. (It doesn't seem to be a problem - the service is acquired correctly; but obviously, we are creating more service trackers than we'd need to and that still gives me a bad feeling).

We are currently switching to a different solution, but I still want to understand how this can happen. Can anyone explain what could go wrong? (JRE is Oracle JRE 1.8.0_141 if it matters).

Edit: the Code above is in a bundle activator (actually in Eclipse/Equinox context). So it can be assumed there is only one instance of the class.

0

There are 0 best solutions below