Не работает двойная проверка блокировки - почему? - PullRequest
0 голосов
/ 07 мая 2020

Мы работаем в контексте OSGi и получаем экземпляры наших сервисов с помощью этой идиомы, которая включает блокировку с двойной проверкой:

  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);
  }

Я думал, что понял основные принципы c (скопируйте в local, используйте volatile для обеспечения порядка), но все же может случиться так, что print в строке X распечатает два разных экземпляра трекера службы. (Кажется, это не проблема - услуга приобретена правильно; но очевидно, что мы создаем больше сервисных трекеров, чем нам нужно, и это все еще вызывает у меня плохое предчувствие).

Мы сейчас перехожу на другое решение, но я все еще хочу понять, как это может произойти. Может кто-нибудь объяснить, что могло go не так? (JRE - это Oracle JRE 1.8.0_141, если это имеет значение).

Изменить: Код выше находится в активаторе пакета (фактически в контексте Eclipse / Equinox). Таким образом, можно предположить, что существует только один экземпляр класса.

...