The Fresh Synchronization


  • Discourse touched me in a no-no place

    Sometimes I come across code that is just astoundingly crazy. This representative line (it's Java) was my find yesterday in one of the more obscure parts of our codebase:

    synchronized (id.toString()) {
    

    The comments nearby indicate that it used to synchronize on id but that caused hangs. Well, the code doesn't hang any more!


    The only implementation of the type of id has the toString() method below. No, it doesn't intern anything. The toUri method is uninteresting beyond the fact that it doesn't cache, but rather makes anew each time. This part is non-WTF-y.

    public String toString() {
        return toUri().toASCIIString();
    }
    


  • The good news is this code will never deadlock. Excellent performance!

    I had to do a double-take on that synchronized bit. Never seen anyone synchronize on the result of a method call... and this certainly is a good example of what not to do.


  • Discourse touched me in a no-no place

    @LoremIpsum said:

    The good news is this code will never deadlock. Excellent performance!

    It'd get better performance by not locking in the first place, especially as the computation of the string is itself expensive.


  • đźš˝ Regular

    @dkf said:

    It'd get better performance by not locking in the first place
    If I read that correctly, then I have good news for you.



  • As much as I like Java, I think the decision to allow programmers to synchronize on any object was a bad one. Similarly for adding wait, notify and so on to the base Object class, where those features should have been assigned specifically to a specialized utility class.



  • @LoremIpsum said:

    As much as I like Java, I think the decision to allow programmers to synchronize on any object was a bad one. Similarly for adding wait, notify and so on to the base Object class, where those features should have been assigned specifically to a specialized utility class.

    What’s even more confusing is that Java also provides dedicaced synchronization objects (Lock, Condition), which also inherit from Object (obviously) and thus get the standard lock/monitor interface.
    On Lock objects, you need to use lock.lock() and lock.unlock() and never use synchronize; on Condition objects, you need to call cond.await() instead of cond.wait, and cond.signal() instead of cond.notify(). If you mix these up, it won’t work correctly.



  • Lock objects didn't exist until Java 1.5 in 2005ish. They were introduced at the same time a bunch of other synchronization tools were introduced (including the various thread-safe collection variants).



  • Yes, the later introduction of the dedicated Lock classes to give programmers better control over synchronization was a cautionary tale.


Log in to reply