3 ms·
Java's concurrency story is weak overall. Nearly all code still uses the old-style "synchronized" blocks, rather than ReentrantLock. This shouldn't be a big s
by colin_mccabe 10y ago
Java's concurrency story is weak overall. Nearly all code still uses the old-style "synchronized" blocks, rather than ReentrantLock. This shouldn't be a big surprise, considering that ReentrantLock was only introduced recently. With synchronized blocks, you don't have any way of releasing the lock other than by exiting the block, which leads to some very contorted-looking code.
The fact that you can synchronize on literally any object means that your object lock is effectively part of your public API. Some other piece of code can easily grab your object, synchronize on it, and then start calling your methods, assuming that this will be atomic. And if you change to use a different lock later, it will break.
Sure you could use BlockingQueue to get some of the benefits of Go channels. But the standard library and pretty much any software you'll interact with were written before BlockingQueue existed, so they won't make use of it. You will have to fight your lonely crusade to use message passing on your own. Which in practice means that you won't be using message passing, just plain old mutexes and volatiles.
In Go, all code runs in goroutines which get multiplexed to kernel threads. In Java, nearly all code is blocking and uses an entire kernel thread. Sure you can use NIO to write an event loop-- just as long as you're careful to never, ever call a blocking function. But nearly every interesting function in Java can block. Including the DNS lookup functions Java provides.
- kmiroslav 10y ago> The fact that you can synchronize on literally any object means that your object lock is effectively part of your public API I'd argue that the fact you can lock on any object is a strength. These days, hardly any Java developer will use synchronized on methods and instead prefer the idiom: public class A { private Object lock = ""; public void foo() { synchronized(lock) { } } This allows Java code to be extremely granular in what gets locked, which has enabled very powerful multithreaded constructs and libraries such as ForkJoinPool and many others described in the Java Concurrency In Practice book.
- eropple 10y agoSo this doesn't map to anything I see in the JVM. It's super interesting that you say it (and I want to stress I'm not calling you a liar or anything, it's just different experiences). Personally? I haven't used synchronized blocks since college (so ~2010 or so). I've been using NIO about that time. I don't feel like I'm swimming upstream using it.