Мы работаем в контексте 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). Таким образом, можно предположить, что существует только один экземпляр класса.