synchronize vs gate

Discussion in 'Java' started by christopher@dailycrossword.com, Jun 3, 2007.

  1. Guest

    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?
     
    , Jun 3, 2007
    #1
    1. Advertising

  2. Lew Guest

    wrote:
    > 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


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

    > 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?


    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.

    --
    Lew
     
    Lew, Jun 4, 2007
    #2
    1. Advertising

  3. Guest

    On Jun 3, 4:08 pm, Lew <> wrote:
    > wrote:
    > > 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

    >
    > Try providing an SSCCE for your example. The use of pseudocode to resolve a
    > Java question is not helpful.
    >
    >
    >
    > > 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?

    >
    > 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.
    >
    > --
    > 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.
     
    , Jun 4, 2007
    #3
  4. Lew Guest

    wrote:
    >>> 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


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


    wrote:
    > 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.

    --
    Lew
     
    Lew, Jun 4, 2007
    #4
  5. Tom Hawtin Guest

    wrote:
    > 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


    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
     
    Tom Hawtin, Jun 4, 2007
    #5
  6. Guest

    *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.
     
    , Jun 4, 2007
    #6
  7. Lew Guest

    wrote:
    > *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


    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.

    --
    Lew
     
    Lew, Jun 4, 2007
    #7
  8. Tom Hawtin Guest

    Lew wrote:
    >
    > 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
     
    Tom Hawtin, Jun 4, 2007
    #8
  9. Lew Guest

    Lew wrote:
    >> The "volatile" keyword provides synchronization, but only fully in the
    >> new memory model.


    Tom Hawtin wrote:
    > 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.

    --
    Lew
     
    Lew, Jun 4, 2007
    #9
  10. Tom Hawtin Guest

    Lew wrote:
    >
    > Tom Hawtin wrote:
    >> 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.


    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
     
    Tom Hawtin, Jun 4, 2007
    #10
  11. On 04.06.2007 02:09, Tom Hawtin wrote:
    > wrote:
    >> 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

    >
    > 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.


    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
     
    Robert Klemme, Jun 4, 2007
    #11
  12. Lew Guest

    Tom Hawtin wrote:
    >>> 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
    >> 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.


    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.


    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?

    --
    Lew
     
    Lew, Jun 4, 2007
    #12
  13. On 04.06.2007 16:37, Lew wrote:
    > Tom Hawtin wrote:
    >>>> 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 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.

    >
    > 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.

    >
    > 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?


    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
     
    Robert Klemme, Jun 4, 2007
    #13
  14. Lew Guest

    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?


    Robert Klemme wrote:
    > 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.

    --
    Lew
     
    Lew, Jun 4, 2007
    #14
  15. On 04.06.2007 17:03, Lew wrote:
    > 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?

    >
    > Robert Klemme wrote:
    >> 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.


    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
     
    Robert Klemme, Jun 4, 2007
    #15
  16. Karl Uppiano Guest

    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.
     
    Karl Uppiano, Jun 6, 2007
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Henning Bahr
    Replies:
    0
    Views:
    1,533
    Henning Bahr
    Aug 18, 2003
  2. Simon S.  IBM
    Replies:
    3
    Views:
    3,593
    B. Joshua Rosen
    Feb 21, 2004
  3. Laurent Gauch

    VHDL gate level from Xilinx XST

    Laurent Gauch, Sep 22, 2004, in forum: VHDL
    Replies:
    0
    Views:
    725
    Laurent Gauch
    Sep 22, 2004
  4. Paddy McCarthy
    Replies:
    3
    Views:
    718
    Anthony J Bybell
    Sep 24, 2004
  5. ralf
    Replies:
    0
    Views:
    1,163
Loading...

Share This Page