[EMAIL PROTECTED] wrote on 2006-05-11 04:31:41 AM:

> Hi,
> 
> I'm looking for some guidelines on the correct way to implement
> thread-safe Declarative Services components. In particular I'm unclear
> regarding which methods I need to make synchronized. Suppose I have a
> component with an optional dependency on the LogService. The component
> code looks something like this:
> 
> public class LoggingComponent {
>     private LogService log;
> 
>     protected void bindLog(LogService log) { this.log = log; }
>     protected void unbindLog(LogService log) { this.log = null; }
> 
>     public void doSomething() {
>         // ...
>         if(log != null) {
>             log.log(LogService.INFO, "Did something");
>         }
>         // ...
>     }
> }

Is the reference to the log service static or dynamic? If static, then you 
do not have to really worry since the bindLog and unbindLog methods will 
be called before activate and after deactivate. If dynamic, then the 
bindLog/unbindLog methods can be called from any thread while you are 
running. So you will need to properly protect access the log field. 
Probably the simplest thing to do is make log volatile and copy to a local 
variable before using.

> 
> I assume that it is possible for unbindLog() to be called between the
> null check and the usage of log, so does this mean that I need to make
> all of these methods synchronized? Alternatively, can I copy the log
> field to a local variable, ie:
> 
>         LogService localLog = log;
>         if(localLog != null) {
>             localLog.log(LogService.INFO, "Did something");
>         }
> 
> Would that always work, or is it possible that the localLog reference
> would become stale before I use it?

In a fully dynamic system like OSGi, there is a chance that the log 
service reference by localLog could be unregistered before using it. 

Thread 1                                                Thread 2

localLog = log;
//thread switch
                                          // log service unregistration 
begins
                                          // SCR receives unregistration 
event
                                          // unbindLog is called
                                          this.log = null;
                                          // log service unregistation 
complete
// At this point localLog refers to a 
// log service object which has been unregistered
// Its behavior is undefined
localLog.log(...)
// result could be a noop or an exception

If you make bindLog, unbindLog and doSomething all synchronized, then 
thread 2 will block trying to call unbindLog since thread 1 is executing 
in doSomething which holds the monitor. Assuming the log(...) method 
doesn't need thread 2 or any monitor currently held by thread 2, the 
synchronized added to your methods will stall the unregistration of the 
log service while you are using it. The risk is a deadlock if the service 
methods you call need something which is owned by thread 2.

> 
> Many thanks,
> Neil
> _______________________________________________
> osgi-dev mailing list
> osgi-dev@bundles.osgi.org
> http://bundles.osgi.org/mailman/listinfo/osgi-dev

BJ Hargrave
Senior Technical Staff Member, IBM
OSGi Fellow and CTO of the OSGi Alliance
[EMAIL PROTECTED]
Office: +1 407 849 9117 Mobile: +1 386 848 3788

_______________________________________________
osgi-dev mailing list
osgi-dev@bundles.osgi.org
http://bundles.osgi.org/mailman/listinfo/osgi-dev

Reply via email to