tag:blogger.com,1999:blog-7290642316743338665.post6821533184269394667..comments2023-09-20T05:23:44.886-05:00Comments on behind the times: 'this' is not the synchronization you're looking forHamlet D'Arcyhttp://www.blogger.com/profile/04008870357169725586noreply@blogger.comBlogger3125tag:blogger.com,1999:blog-7290642316743338665.post-26042492069487323962008-01-08T09:02:00.000-06:002008-01-08T09:02:00.000-06:00Well, to be fair, that links says that synchroniza...Well, to be fair, that links says that synchronization isn't terribly unslow. Their example -- the uncontended case -- is the boring one. That's like saying that GC is fast when there are no objects to clean: who cares?<BR/><BR/>Synchronization is always well worth it, though, since correctness trumps performance every time: I can always write super fast code that doesn't work. That's not the hard part.Robert Fischerhttps://www.blogger.com/profile/17844778275497805797noreply@blogger.comtag:blogger.com,1999:blog-7290642316743338665.post-17625353469806564532008-01-08T06:46:00.000-06:002008-01-08T06:46:00.000-06:00The AtomicInteger and AtomicBoolean classes in Jav...The AtomicInteger and AtomicBoolean classes in Java 5 are a nice addition, and worth a look. In this particular example AtomicInteger would actually change the behavior to not run the 10,000 increments atomically. In real life (tm) I find I commonly turn to AtomicBoolean as a way to track whether objects have been released. I've been hosting COM objects from Java code lately, so this is a frequent need for me. <BR/><BR/>Goetz's book recommends as fine grained locking as possible. And the presentation here says that acquiring locks in Java 5 is performant: www.scribd.com/doc/248581/Java-Tech-Performance-MythsHamlet D'Arcyhttps://www.blogger.com/profile/04008870357169725586noreply@blogger.comtag:blogger.com,1999:blog-7290642316743338665.post-13355836888428687592008-01-07T21:35:00.000-06:002008-01-07T21:35:00.000-06:00Well, I still don't quite understand why double-ch...Well, I still don't quite understand why double-checked locking is broke in Java, but aside from that, <A HREF="http://code.google.com/p/jconch/" REL="nofollow">I grok concurrency pretty well</A>.<BR/><BR/>I do agree that slapping the "synchronized" keyword into the method name is kinda exposing implementation, but it's better than "synchronized(this)" -- the reason is because there's a piece of state (specifically, a monitor and its locks) that you're obscuring from the user. And that's just begging for a concurrency bug.<BR/><BR/>Your monitors should either be purely internal (meaning no reference to a synchronization lock escapes the object), or clearly externalized in the API (either through a lock API or having methods be "synchronized").<BR/><BR/>In general, you should synchronize as tightly as possible in order to allow liveness, and if you can pawn the synchronization off into an member, all the better -- in this case, you'd be better off using something like <A HREF="http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/atomic/AtomicInteger.html" REL="nofollow">AtomicInteger</A>. <BR/><BR/>This guideline goes in the face of performance people, who will tell you that acquiring and releasing locks is an expensive proposition, and that you should have as coarse-grained locks as possible. As you discovered, though, this tends to result in crappy concurrency and (often) buggy code. So the tighter locks are better, even if they're less performant -- if you don't like that, <A HREF="http://jocaml.inria.fr/" REL="nofollow">use a language whose concurrency model doesn't suck</A>.<BR/><BR/>The other option (and this is actually better) is to simply not share non-thread-safe objects between multiple threads. Better yet, only share read-only objects (incl. interfaces which are read-only) between threads: they don't need any locking at all, so that'll give you maximum liveness.Robert Fischerhttps://www.blogger.com/profile/17844778275497805797noreply@blogger.com