[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