Step 5 happens before step 1. I’m not sure that java by itself has sufficient synchronization to assure that a requesting thread gets the fully correct memory set up by thread T1. However I Think that with the synchronization in Felix DS requesting threads will get correct information.
thanks david jencks > On Apr 28, 2017, at 1:13 AM, Julian Sedding <jsedd...@gmail.com> wrote: > > 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 >>