felix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From BJ Hargrave <hargr...@us.ibm.com>
Subject Re: Contribution of the dependency manager to Feli
Date Mon, 30 Jan 2006 18:53:51 GMT
Marcel Offermans <marcel.offermans@luminis.nl> wrote on 2006-01-30 
11:53:59 AM:

> BJ Hargrave wrote:
> >Interesting. With the possible asynchronous changes to the field being 
> >made by the dependency manager, the field MUST be declared volatile or 
> >access to it must be protected by a suitable synchronization for proper 

> >java memory model semantics. Otherwise strange and hard to debug 
> >may arise since different threads can end up using different values for 

> >the field.
> > 
> >
> Yes, this is an issue that I am aware of. First of all, you can solve 
> this problem by using volatile as you suggest. If you need more control, 

> it is probably better to use the callback hooks.
> >How do you deal with this? While for the log example here, no serious 
> >problems will arise if the wrong log is used. But if the field 
> >some other service, serious bugs could occur.
> > 
> >
> Even if you do not use volatile, I tried to make sure that changes to 
> the field are written to memory. I read about the Java Memory Model on 
> various sites and finally got the following information from Doug Lea:
> http://gee.cs.oswego.edu/dl/cpj/jmm.html
> Here he writes (about visibility):
> "In essence, releasing a lock forces a flush of all writes from working 
> memory employed by the thread, [...] While lock actions provide 
> exclusion only for the operations performed within a synchronized method 

> or block, these memory effects are defined to cover all fields used by 
> the thread performing the action.

As this quote points out, it only affects the thread's working memory 
which includes the field. So when the synchronized region is exiting, the 
thread (and it processor) will flush caches to main memory. However, the 
client code may be running on another thread/processor and its processor 
cache will not be synchronized with main memory. This is why both threads 
will need to either treat the field as volatile or both protect access to 
the field with a synchronized region.

>  Note the double meaning of synchronized: it deals with locks that 
> permit higher-level synchronization protocols, while at the same time 
> dealing with the memory system (sometimes via low-level memory barrier 
> machine instructions) to keep value representations in synch across 
> threads. This reflects one way in which concurrent programming bears 
> more similarity to distributed programming than to sequential 
> programming. The latter sense of synchronized may be viewed as a 
> mechanism by which a method running in one thread indicates that it is 
> willing to send and/or receive changes to variables to and from methods 
> running in other threads. From this point of view, using locks and 
> passing messages might be seen merely as syntactic variants of each 
> So in the dependency manager (ServiceImpl class) I have the following 
> code fragment to update a field through reflection:
>     synchronized (new Object()) {

Isn't new Object() a wasted memory allocation? Simply use some object you 
allocate only once :-)

>         fields[j].set(m_serviceInstance, instance);
>     }
> As far as I can tell, as soon as the code leaves this synchronized 
> block, the field is written to memory.

Yes. It should be forced to main memory. This does not mean that other 
threads which read the field will synchronize their processor's cache with 
main memory.

> Note that I don't think this will guarantee that all threads that read 
> this variable will automatically re-fetch their cached copy but as far 
> as I can see there's not much I can do about that (apart from having 
> people define such fields as volatile).

Well you could force that all such fields be declared volatile. You can 
make this part of your specification and enforce via reflection. That is, 
do not set the field if it is not declared volatile. If you don't do 
something like this, then your model is dangerous to use since it is 
inherently not thread-safe and may lead to unpredictable bugs.

> But any input on this is very welcome. It's a tricky subject but very 
> important to get right.

A more complex solution to this was proposed by Peter Kriens. It involves 
bytecode weaving to replace the field with a method call. This method can 
then always perform the proper actions to enforce the java memory model.

> Greetings, Marcel

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

View raw message