My theory is as follows: 1. DS creates a new instances of the service S1 in thread T1 2. DS injects the (static) @Reference service in thread T1 3. DS calls activate() in thread T1 4. at this time no other thread has a reference to service S1 5. DS publishes the service in the OSGi service registry 6. at this time other thread can get a fully initialized reference to service S1
I believe that because up to 4. the reference to S1 is "private" to thread T1. In 5. S1 is "published" and thus first allowed to cross a thread boundary (I assume Java internally creates some sort of copy of S1's memory for a new thread T2). However, at that point S1 is fully initialized and immutable. Should the static @Reference on S1 change, it is deactivated and a new instance S1' is created, activated and registered. In contrast, with a dynamic @Reference, the field's value may change after it is published. Thus it needs to be volatile. As I said, this is a theory ;) I have no references to back me up. Regards Julian On Thu, Apr 27, 2017 at 7:06 PM, David Jencks <david.a.jen...@gmail.com> wrote: > My theory about why this is ok is as follows, perhaps you can see something > wrong with it. > > Felix DS has some synchronization after activate is called, therefore the > state of the static reference is definitely written to memory. This > reference field won’t change after that, since it’s (SCR) static. > Any getService call on the service reference also has sufficient > synchronization that it happens after the above write. Therefore any other > thread which obtained the referenced service will get an object with the > correct field value. Therefore any access to this possibly cached object by > any thread will have the correct value. > > thanks > > david jencks > >> On Apr 27, 2017, at 9:33 AM, Dirk Hogan <dirk.ho...@forgerock.com> wrote: >> >> I have been puzzled about the visibility of references written/read across >> threads in Felix. >> >> Scenario: >> >> public class myOSGiComponent { >> >> @Reference >> >> SomeOtherOSGiService myServiceReference; >> >> public void activate(ComponentContext cc) { >> >> // myServiceReference will be set - use it to initialize other >> dependencies, etc >> >> } >> >> public void clientRequestViaEmbeddedJetty() { >> >> myServiceReference.foo(); >> >> } >> >> The bottom line is that a STATIC reference does not have to be volatile. I >> can see that the write to myServiceReference is guaranteed to be visible in >> the activate method, provided that same Felix thread which set >> myServiceReference invokes activate, and thus the visibility is guaranteed >> by program order (17.4.3 of the Java Language Spec). >> >> However, in the absence of the synchronization action provided by e.g. a >> volatile @Reference declaration, I do not see how Felix can provide a Java >> Memory Model compliant guarantee that myServiceReference will be visible in >> clientRequestViaEmbeddedJetty, as the thread which set the reference, and >> the thread which invokes clientRequestViaEmbeddedJetty, will be distinct. >> In the absence of a volatile @Reference declaration, there is no >> synchronization action (17.4.2 of JLS) which would guarantee that the >> reference write is visible to the reference read, as they are being >> performed by distinct threads. >> >> Perhaps an explanation as to why a DYNAMIC @Reference does need to be >> volatile would be helpful - e.g. why does component >> de-activation/re-activation provide memory visibility guarantees for STATIC >> references? >> >> >> Thanks >> >> >> Dirk >