users@jaxb.java.net

Re: Binding customization for "synchronized"

From: Franklin, Brian <brian.franklin_at_ciraden.com>
Date: Wed, 23 Apr 2003 15:36:07 -0400

Kohsuke,

I generally agree with your analysis. I'd like to explore the analysis a
little
further, if you don't mind. Pardon me if some of the analysis is obvious to
you,
but perhaps it may help someone else on the list less familiar with the
concepts,
or will at least serve as a good record for the archive.

But first, a bit of an aside: I believe I brought this issue up originally
while JAXB was still EA. Obviously, it's an RFE, not a bug. It came up
again
in the recent community forum/chat with Ryan and Sekhar primarily because it
just happened to be one of my questions that got approved by the moderator.
There were others that I considered higher-priority or more interesting.
Further, I rarely consider having to type a couple of extra lines of code
here and there justification for some optimization, especially at the
point where functionality is still growing; however, this issue leaks
over a little more into the need for simplicity and clarity of code (on
the developer side, not within JAXB's code).

Now, back to the implications of the issue and any solution...

I would say that the issue of concurrency and synchronization can be
approached on many levels of granularity, which I believe your List
example brings up. I can think of three primary levels of granularity
to be explored relating to my issue. On what is perhaps the finest grain,
each property would have a separate lock for the property's field.
So a section of the generated code might look like this:

-- Example 1: Generated Impl class excerpt --

        private String name = null;
        private final Object nameLock = new Object();

        private String address = null;
        private final Object addressLock = new Object();

        public void setName(String name) {
                synchronized (nameLock) {
                        this.name = name;
                }
        }

        public String getName() {
                synchronized (nameLock) {
                        return this.name;
                }
        }

        public void setAddress(String address) {
                synchronized (addressLock) {
                        this.address = address;
                }
        }

        // and so on...
-- end --

Now, while I can easily say that this is a bit of overkill, it does
have arguable advantages, even if they are minimally pragmatic.

The medium level of granularity would be to synchronize all property
manipulation across the entire class. I see two ways in which this
could be accomplished. One way (call it 2a) is to use an internal
object as a lock. This might look something like this:

-- Example 2: Generated Impl class excerpt --

        private final Object lock = new Object();

        private String name = null;
        private String address = null;

        public void setName(String name) {
                synchronized (lock) {
                        this.name = name;
                }
        }

        public String getName() {
                synchronized (lock) {
                        return this.name;
                }
        }

        public void setAddress(String address) {
                synchronized (lock) {
                        this.address = address;
                }
        }

        // and so on...
-- end --

In this case, there is the option of revealing the internal lock object
or not, whether via a getLock() method or by making the lock field public.

The alternative way (call it 2b) is to use the instance of the class itself
as the lock
object, which is essentially what I describe in my original post, where
the get and set methods have the "synchronized" modifier. One side effect
of this in contrast to the other approach is that the lock object is always
visible. I will come back to this approach after the next section.

On the coarsest-grained level, client code (i.e. code that has a reference
to and is manipulating an instance of the schema-derived class) that is
executing
in a multi-threaded environment would handle all sychronization and locking
itself,
through some object completely separate from the generated class instance.
This might look something like:

-- Example 3: Client code excerpts --

        INSIDE THREAD 1:
        ConfigurableComponent component = xxx.getConfigurableComponent();
        ComponentConfiguration config = component.getConfiguration();
        String name = null;
        sychronized (externalConfigLock) {
                name = config.getName();
        }

        INSIDE THREAD 2:

        ConfigurableComponent component = xxx.getConfigurableComponent();
        ComponentConfiguration config = component.getConfiguration();
        synchronized (externalConfigLock) {
                config.setName("new name");
        }

-- end --

... or, to do your List example justice, something like this ...

-- Example 3b: Client code excerpts --

        SOMEWHERE:
        (public/private) (static/not) final Object externalConfigLock = new
Object();

        INSIDE THREAD 1:
        ConfigurableComponent component = xxx.getConfigurableComponent();
        ComponentConfiguration config = component.getConfiguration();
        List names = null;
        /* BAD VERSION - WOULD BE SYNCH. PROBLEM */
        // sychronized (externalConfigLock) {
        // names = config.getNameList();
        // }
        // names.remove("some name");
        /* GOOD VERSION */
        sychronized (externalConfigLock) {
                names = config.getNameList();
                names.remove("some name");
        }

        INSIDE THREAD 2:

        ConfigurableComponent component = xxx.getConfigurableComponent();
        ComponentConfiguration config = component.getConfiguration();
        /* BAD VERSION - WOULD BE SYNCH. PROBLEM */
        // sychronized (externalConfigLock) {
        // names = config.getNameList();
        // }
        // names.add("some name");
        /* GOOD VERSION */
        sychronized (externalConfigLock) {
                names = config.getNameList();
                names.add("some name");
        }

-- end --

The coarse-grained example has several other factors involved. One is
where the lock object is located and handling how it is accessed and
shared among the threads. The other is, as you mentioned, synchronizing
manipulation of sub-properties (i.e. collections and other non-primitive
mutable objects). As far as collections are concerned, they could be
wrapped in the generated Impl class using Collections.sychronized[whatever].

This obviously does not help the other non-primitive mutable objects case,
so it shouldn't really be considered a solution.

The best way, I believe, would be a blend of approaches 2b and 3. The
sychronization solution does not have to be relegated to only one
level of granularity. The existence of Collections.synchronized[whatever]
itself I believe shows this, since it solves medium-granularity but not
coarse-granularity. Approach 2b (putting the synchronized modifier
on the gets/sets) would solve the most direct synchronization problems
relating to the references to the object's properties themselves.
Approach 3 would be used in cases where complex properties, like lists and
such, did need that extra level of external synchronization, but there
would be an obvious lock object to use--the configuration object itself.

You would not have to worry about which lock object you should use for which
reference, nor have to figure out how to access or share it among threads.
It would be inherent. The possibility of buggy code would be reduced since
the number of explicit synchronizations that would have to be made
in client code would be reduced. The client code would also be cleaner and
easier to understand.

To demonstrate, you might have something like this:

-- Final Combined Example: Generated Impl class excerpt --

        private String name = null;
        private List addressList = new ArrayList();
        // Perhaps even: Collections.synchronizedList(new ArrayList());

        public sychronized void setName(String name) {
                this.name = name;
        }

        public sychronized String getName() {
                return this.name;
        }

        public synchronized void getAddressList() {
                return this.addressList;
        }

-- end --

-- Final Combined Example: Client code excerpts --

        INSIDE THREAD 1:
        ConfigurableComponent component = xxx.getConfigurableComponent();
        ComponentConfiguration config = component.getConfiguration();
        String name = config.getName();

        INSIDE THREAD 2:

        ConfigurableComponent component = xxx.getConfigurableComponent();
        ComponentConfiguration config = component.getConfiguration();
        config.setName("new name");

        INSIDE THREAD 3:
        ConfigurableComponent component = xxx.getConfigurableComponent();
        ComponentConfiguration config = component.getConfiguration();
        sychronized (config) {
                config.getAddressList().remove(someAddress);
        }

        INSIDE THREAD 4:

        ConfigurableComponent component = xxx.getConfigurableComponent();
        ComponentConfiguration config = component.getConfiguration();
        synchronized (config) {
                config.getAddressList().add(someAddress);
        }

-- end --

I think that's all. My apologies that it turned out to be so long.
Does that help you understand my analysis of the situation more?
(BTW, I can't wait for Doug Lea's concurrency utils package in JDK1.5.
I already use the existing version of the utils.)

Thanks for your time,

Brian Franklin

-----Original Message-----
From: Kohsuke Kawaguchi [mailto:Kohsuke.Kawaguchi_at_Sun.COM]
Sent: Wednesday, April 23, 2003 10:22 AM
To: JAXB-INTEREST_at_JAVA.SUN.COM
Subject: Re: Binding customization for "synchronized"


One thing that I'm not sure is that when you have multiple threads
accessing the same data structure, you'd probably want more
coarse-grained lock, wouldn't you.

For example, when I have a list data structure (which consists of many
objects), then I'd want to lock the entire list, not just individual
cells in the list, before I start to modify it.

To me, the same thing holds with JAXB generated classes. It doesn't make
much sense to me to use "I'm modifying this object so don't touch it but
you can modify other objects freely" kind of lock. It would make more
sense to me to use "don't touch this region of the content tree" kind of
lock.

So in that case, I'd probably want to use a separate lock objects.

Is per-object lock really what you want?

regards,
--
Kohsuke KAWAGUCHI                  408-276-7063 (x17063)
Sun Microsystems                   kohsuke.kawaguchi_at_sun.com