Hi Neil-
I agree that, upon publication, the service has been activated, and thus
all references are visible to the thread which performed the publication.
But the java memory model explicitly distinguishes between:
---Program order: which guarantees that the underlying virtual machine must
ensure that memory state matches program execution sequence despite
omnipresent compiler re-orderings. This only applies to the execution
thread - i.e. intra-thread visibility
---Synchronization order: which dictates memory visibility across threads.
Unless there is an explicit Synchronization Action, there is NO guarantee
that thread A can read what thread B wrote.

So yes, when Felix initializes a component and publishes a service, all of
its references are set and visible to the Felix thread which performed this
action. But no similar guarantee applies when another thread hits the
component, unless there is an explicit Synchronization Action between the
write performed by the Felix thread, and the read performed by another
thread.

Remember the 'thread shutdown idiom', where you had a thread A running in a
while(!shutdown) loop, and a shutdown() method to toggle shutdown to true
so that thread A shuts down? The shutdown boolean had to be declared as
volatile so the write to the shutdown boolean performed by thread X would
be visible to the read performed by thread A in the while(!shutdown) loop.
In the shutdown() method, after having set shutdown to true, thread X is
guaranteed to always see a value of true for the shutdown boolean, but it
is completely valid for thread A to see either true or false.

These two links are a great resource:
https://shipilev.net/blog/2016/close-encounters-of-jmm-kind/
https://shipilev.net/blog/2014/jmm-pragmatics/

Thanks

Dirk

On Mon, May 1, 2017 at 4:03 PM, Neil Bartlett <njbartl...@gmail.com> wrote:

> Dirk,
>
> But this is why the happens-before relationship is important. The
> component is not published as a service until after activation, therefore
> no other thread can obtain visibility in order to “hit” it until after the
> references are bound.
>
> For this reason, static @Reference fields do not need to be volatile.
>
> Regards,
> Neil
>
>
>
> > On 1 May 2017, at 22:05, Dirk Hogan <dirk.ho...@forgerock.com> wrote:
> >
> > Hi Neil-
> >
> > I was not so worried about the happens-before relationship between
> > setting the @Reference and activating the component. This relationship
> > could be provided by the memory visibility guarantees of the program
> > order defined in the JMM, provided @Reference set and component
> > activation occurred in the same thread.
> >
> >
> > I was more worried about some other thread (e.g. client request)
> > hitting this component, and, in the process, dereferencing the
> > @Reference, as this will involve inter-thread memory visibility, and
> > as such, a synchronization action to ensure that a memory read sees
> > the state written by OSGi thread which wrote the @Reference.
> >
> >
> > Thanks
> >
> >
> > Dirk
> >
> >
> >
> > The Declarative Services spec requires that there is a happens-before
> > relationship between SCR setting the field and activating the component
> > instance — see OSGi Compendium 6.0.0 section 112.3.8.1.
> >
> > There are various ways of achieving this under the Java Memory Model. For
> > example the SCR implementation can use internal synchronized blocks.
> >
> > Regards,
> > Neil
> >
> >> On 27 Apr 2017, at 17:33, 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
>
>

Reply via email to