Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / June 2007

Tip: Looking for answers? Try searching our database.

synchronize vs gate

Thread view: 
christopher@dailycrossword.com - 03 Jun 2007 20:43 GMT
I have a singleton in a web service that provides a collection and
self-updates it on a periodic basis:

doSelfUpdate()

 create temporary collection (time consuming)
 syncronize
   update temporary collection from current collection (fast)
   create temporary reference 'old' to current collection
   point current collection reference to temporary collection
 end syncronize
 do stuff with 'old' collection (time consuming)
 done

getCollection()
 synchronize
 just waiting on monitor
 end synchronize
 return collection
 done

It seems to me each thread accessing the getCollection method must
wait on the monitor every time it is accessed -- which is not what I
want.  I just want to open and close the gate for a few milliseconds
while the self-update is being done.  What do y'all think about
something like this:

boolean isBusy=false;

doSelfUpdate()
 create temporary collection
 isBusy=true;
   update temporary collection from current collection
   create temporary reference 'old' to current collection
   point current collection reference to temporary collection
 isBusy=false;
 do stuff with 'old' collection
 done

getCollection()
 maxWait=10000
 waited=0
 while(isBusy && waited <maxWait) {
    waited+=500
   if(waited>=MaxWait) log error;
    wait 500
    }
 return collection
 done

IMHO this means each thread consuming getCollection is a tiny bit
slower because it has a condition that must be tested, but as a group
they are not waiting in line for the monitor.  Is this right?
Lew - 04 Jun 2007 00:08 GMT
> I have a singleton in a web service that provides a collection and
> self-updates it on a periodic basis:
[quoted text clipped - 9 lines]
>   do stuff with 'old' collection (time consuming)
>   done

Try providing an SSCCE for your example.  The use of pseudocode to resolve a
Java question is not helpful.

> getCollection()
>   synchronize
[quoted text clipped - 35 lines]
> slower because it has a condition that must be tested, but as a group
> they are not waiting in line for the monitor.  Is this right?

Assuming you mean the obvious transliteration to Java (e.g., that the producer
and consumer methods run in separate threads), your second form will not work.
 getCollection() might return a version of collection containing none of the
updates from invocations of doSelfUpdate() in other threads.  In a heavily
parallelized situation with multiple-core servers you very likely would end up
with corrupted results.

(Incidentally, "collection" is an inadvisable name for a variable.)

Another thing is that your "wait" times are entirely arbitrary (also
unspecified in your post).  On what basis do you assess that any time you
choose is greater or less than the time it would take to acquire a monitor?

Stick with the correct use of synchronization.  You need to use concurrent
idioms to handle concurrent issues.

Signature

Lew

christopher@dailycrossword.com - 04 Jun 2007 00:47 GMT
> christop...@dailycrossword.com wrote:
> > I have a singleton in a web service that provides a collection and
[quoted text clipped - 72 lines]
> --
> Lew

thanx lew -- I don't care if the consumer gets an exact copy as long
as each copy it is internally consistent.  Sorry if I did not phrase
my question well.  I am not asking which runs faster or which takes
less time.  I am asking if I use synchronization doesn't each thread
always have to wait for one and only one monitor?  If I don't need
everyone to have an exact copy -- only an internally consistent one --
can't I simply gate the process (with an arbitrary wait and retry)?
In my mind (such as it is) all the consuming threads are waiting at
the same time *only* while the singleton updates, rather than always
waiting for each other.
Lew - 04 Jun 2007 01:07 GMT
>>> What do y'all think about something like this:
>>> boolean isBusy=false;
[quoted text clipped - 17 lines]
>>>   return collection
>>>   done

Lew wrote:
>> Stick with the correct use of synchronization.  You need to use concurrent
>> idioms to handle concurrent issues.

> thanx lew -- I don't care if the consumer gets an exact copy as long
> as each copy it is internally consistent.  Sorry if I did not phrase

Do you care if a consumer /never/ gets the updates from a producer?  That is
the risk with the second idiom you provided.

> my question well.  I am not asking which runs faster or which takes
> less time.

And I wasn't answering such a question.  I was answering the question of
whether your so-called "gate" approach would work at all.

> I am asking if I use synchronization doesn't each thread always have to wait for one and only one monitor?  If I don't need
> everyone to have an exact copy -- only an internally consistent one --
> can't I simply gate the process (with an arbitrary wait and retry)?

No.  If you do that the consumer might see none of the changes made by the
producer(s), ever, or might get an inconsistent view.

> In my mind (such as it is) all the consuming threads are waiting at
> the same time *only* while the singleton updates, rather than always
> waiting for each other.

Read the threading tutorials on Sun and elsewhere.

I don't know what problem you imagine you are avoiding by not synchronizing,
but you aren't.  A thread waits on a monitor only until another one releases
it.  It is the "waiting for one and only one monitor" that makes the code
work; abandoning that is a recipe for disaster.  Don't do it.

Your so-called "solution" to the non-existent "problem" will potentially cause
threads to run much slower than with correct synchronization, orders of
magnitude, several orders of magnitude, depending on your choice of "wait"
[sic] times, and also to get very wrong results.

For a related "broken solution" see
<http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html>

Use synchronization.  Do not use your "gate" approach.  And start using Java
for your examples.
<http://mindprod.com/jgloss/sscce.html>
<http://www.physci.org/codes/sscce.html>

Study threading and concurrency, and pay special attention to the Java "memory
model".

Forget the gate.  Use synchronization.

Signature

Lew

christopher@dailycrossword.com - 04 Jun 2007 07:03 GMT
*snip*
> Forget the gate.  Use synchronization.
>
> --
> Lew

lew
I have erased 4 replies to you already, so I will leave it at this --
I appreciate your time, I am not the dufus you seem to think I am, and
I will continue to use pseodocode (as I have for 20 years) against
your recommendation.  I usually top-post, too.

No one would argue that *is not* a problem to use synchronized where
it is unnecessary, and I believe in this case it is not.  I am not
certain (obviously) and would welcome a circumstance that proves me
wrong, rather than a link to andrew's glossary gergoshsake, and some
random page (double locking??) that is completely irrelevant.

Tom, I am using 1.4 until next week when my new server is online (1.5
doesn't run on this old beast), so 'volatile' has not been an option.
I will look into it, as I think you have hit the nail on the head.
Lew - 04 Jun 2007 14:29 GMT
> *snip*
>> Forget the gate.  Use synchronization.
[quoted text clipped - 5 lines]
> I have erased 4 replies to you already, so I will leave it at this --
> I appreciate your time, I am not the dufus you seem to think I am, and

How do you conclude that I think that?  I surely do not.

> I will continue to use pseodocode (as I have for 20 years) against
> your recommendation.  I usually top-post, too.

The problem with pseudocode in a Java-specific question is that it obscures
the very issues you are trying to resolve.  I am not against pseudocode, only
in favor of examples that actually exemplify.

Pseudocode cannot help resolve your question of whether to use
synchronization, which volatile is part of, because your question of
synchronization is particular to Java semantics.

As for top-posting, that's just deliberate rudeness.  I can't believe you're
actually bragging about it.

> No one would argue that *is not* a problem to use synchronized where
> it is unnecessary, and I believe in this case it is not.  I am not

But synchronization /is/ necessary, that is my point.  Why do you ignore it?

Your "gate" idiom simply would not work reliably in a multithreaded context.
That was the point.

> certain (obviously) and would welcome a circumstance that proves me
> wrong, rather than a link to andrew's glossary gergoshsake, and some
> random page (double locking??) that is completely irrelevant.

If you find it irrelevant, it's because you missed the point.

> Tom, I am using 1.4 until next week when my new server is online (1.5
> doesn't run on this old beast), so 'volatile' has not been an option.
> I will look into it, as I think you have hit the nail on the head.

The "volatile" keyword provides synchronization, but only fully in the new
memory model.  It is part of Java's synchronization mechanism, which I
mentioned was required for your code to succeed.  It does work in 1.4, but
differently.  I will forgo sending you the links that explain the differences,
or the dangers.

Signature

Lew

Tom Hawtin - 04 Jun 2007 14:37 GMT
> The "volatile" keyword provides synchronization, but only fully in the
> new memory model.  It is part of Java's synchronization mechanism, which
> I mentioned was required for your code to succeed.  It does work in 1.4,
> but differently.  I will forgo sending you the links that explain the
> differences, or the dangers.

As I understand it, 1.4 complies with the 1.5 spec in this regard.

Tom Hawtin
Lew - 04 Jun 2007 15:05 GMT
Lew wrote:
>> The "volatile" keyword provides synchronization, but only fully in the
>> new memory model.  

> As I understand it, 1.4 complies with the 1.5 spec in this regard.

They changed the memory model in Java 5, incorporating JSR 133.  Among other
changes, in 1.4 "volatile" only protected the given variable against
synchronization issues.  In J5+, all writes prior to a write to a volatile
variable are readable by a thread that subsequently reads that volatile
variable.  This was the introduction of the "happens-before" concept.  Now
"volatile" is a much more powerful synchronization construct, much closer to
"synchronized" itself.

Signature

Lew

Tom Hawtin - 04 Jun 2007 15:29 GMT
>> As I understand it, 1.4 complies with the 1.5 spec in this regard.
>
[quoted text clipped - 5 lines]
> "happens-before" concept.  Now "volatile" is a much more powerful
> synchronization construct, much closer to "synchronized" itself.

As I say, as I understand it, the actual implementation of 1.4 complies
with the 1.5 spec. Most of the tricky work of JSR 133 seems to have been
coming up with a formalisation.

Tom Hawtin
Lew - 04 Jun 2007 15:37 GMT
>>> As I understand it, 1.4 complies with the 1.5 spec in this regard.

Lew wrote:
>> They changed the memory model in Java 5, incorporating JSR 133.  Among
>> other changes, in 1.4 "volatile" only protected the given variable
[quoted text clipped - 3 lines]
>> "happens-before" concept.  Now "volatile" is a much more powerful
>> synchronization construct, much closer to "synchronized" itself.

> As I say, as I understand it, the actual implementation of 1.4 complies
> with the 1.5 spec. Most of the tricky work of JSR 133 seems to have been
> coming up with a formalisation.

That is very interesting information.  I googled around quite a bit before
answering, and all I found was JSR 133 results from 2004, well after 1.4 came
out, and of course the JLS 3rd claims that the new memory model was only since
J5.  I had no idea any 1.4 implementation already embodied the behavior.

Every reference I've read about the memory model referred to 1.4 as
implementing the "old" semantics and 5+ the "new", insofar as they mention it
at all.

I presume you are referring specifically to Sun's implementation of 1.4.  Do
you know if it was only Sun, or all 1.4 implementations, or some other set
that implemented the "new" semantics?

Signature

Lew

Robert Klemme - 04 Jun 2007 15:56 GMT
>>>> As I understand it, 1.4 complies with the 1.5 spec in this regard.
>
[quoted text clipped - 25 lines]
> 1.4.  Do you know if it was only Sun, or all 1.4 implementations, or
> some other set that implemented the "new" semantics?

I believe most of the discussion was about the memory /model/ being
flawed, not the /implementations/.  So while implementations most of the
time did what was reasonable the JLS did not enforce this behavior which
in turn could lead to issues.  Some of the discussion can be found here,
I believe:

http://www.cs.umd.edu/~pugh/java/broken.pdf
http://www.cs.umd.edu/~pugh/java/memoryModel/

http://www.ibm.com/developerworks/library/j-jtp02244.html
http://www.ibm.com/developerworks/library/j-jtp03304/

http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg00404.html

Kind regards

    robert
Lew - 04 Jun 2007 16:03 GMT
Tom Hawtin wrote:
>>> As I say, as I understand it, the actual implementation of 1.4
>>> complies with the 1.5 spec. Most of the tricky work of JSR 133 seems
>>> to have been coming up with a formalisation.

Lew wrote:
>> I presume you are referring specifically to Sun's implementation of
>> 1.4.  Do you know if it was only Sun, or all 1.4 implementations, or
>> some other set that implemented the "new" semantics?

> I believe most of the discussion was about the memory /model/ being
> flawed, not the /implementations/.  So while implementations most of the
> time did what was reasonable the JLS did not enforce this behavior which
> in turn could lead to issues.

Which is why I'm curious which 1.4 JVM's implemented the "broken" behavior,
and which implemented the behavior later formalized in JSR133.

In any event, I wouldn't recommend to the OP that they rely on behavior of the
1.4 JVM that is not enforced by the JLS for that version.  Not only that, but
Sun's 1.4 implementation is now officially in "End-of-Life", and the OP has
stated that they are on the verge of moving to the next old Java version, so
the point is moot for them.

Signature

Lew

Robert Klemme - 04 Jun 2007 16:20 GMT
> Tom Hawtin wrote:
>>>> As I say, as I understand it, the actual implementation of 1.4
[quoted text clipped - 13 lines]
> Which is why I'm curious which 1.4 JVM's implemented the "broken"
> behavior, and which implemented the behavior later formalized in JSR133.

I /believe/ Sun's JDK's were ok but I cannot give you references to
material confirming this.  I'm sorry.

> In any event, I wouldn't recommend to the OP that they rely on behavior
> of the 1.4 JVM that is not enforced by the JLS for that version.  Not
> only that, but Sun's 1.4 implementation is now officially in
> "End-of-Life", and the OP has stated that they are on the verge of
> moving to the next old Java version, so the point is moot for them.

Yeah, definitively agree!

Kind regards

    robert
Tom Hawtin - 04 Jun 2007 01:07 GMT
> I have a singleton in a web service that provides a collection and
> self-updates it on a periodic basis:
[quoted text clipped - 16 lines]
>   return collection
>   done

The obvious thing to do (from Java 1.5 spec, and 1.4 implementation) is
to make the reference to the collection volatile. Keep the lock in
doSelfUpdate, but not getCollection. Alternatively just use
java.util.concurrent.ConcurrentHashmap.

Tom Hawtin
Robert Klemme - 04 Jun 2007 15:30 GMT
>> I have a singleton in a web service that provides a collection and
>> self-updates it on a periodic basis:
[quoted text clipped - 21 lines]
> doSelfUpdate, but not getCollection. Alternatively just use
> java.util.concurrent.ConcurrentHashmap.

Yet another alternative would be to use a ReadWriteLock that is held
during update of the reference only and use an immutable collection.
This of course works best if it is made sure through other means that
there is just one updater at a time - although two concurrent updaters
might only cost additional CPU.  The logic should still work, you only
get two (or n) updates of the reference in a short period of time.  If
the update process itself needs additional synchronization that can be
either provided by another Lock or different logic.  Difficult to
speculate without knowing more detail...

Kind regards

    robert
Karl Uppiano - 06 Jun 2007 04:38 GMT
In my 10 years of writing in Java, I only found the need to roll my own
synchronization one time: We needed a Mutex or CriticalSection, and prior to
1.5, Java had no such thing. We finally got it working, but it was a
nightmare.

People tend to think the original Java synchronization was lame, but it is
surprising how well it works, and how rarely you need anything else.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.