5 ms·
> When is concurrency in Java ever hard? Potentially-racey stuff: * Synchronized primitives don't compose. You can safely `synchronized get(...)` and safely
by mrkeen 7y ago
> When is concurrency in Java ever hard?
Potentially-racey stuff:
* Synchronized primitives don't compose. You can safely `synchronized get(...)` and safely `synchronized put(...)`. But their composition put(get(...)+1) isn't synchronized. And it's hard to mentally revisit it at the end of the day: if you have a class with some methods marked synchronized, nothing will tell whether you've synchronized the right methods. You just have to think it through again and hope you reach the same conclusions as before.
Other (non-racey) stuff:
* Threads are heavy, CompletableFutures are light. But CFs lack the functionality of Threads. A CF can't decide to sleep for a while, nor can it be cancelled. (As an aside, BEAM threads are super light).
- discreteevent 7y agoJava has a large set of higher level abstractions for concurrency. You don't have to use low level locks but you can. (And that's just Java, there's also Scala, clojure ...)
- throwaway894345 7y agoI'm pretty firmly in the "shared memory parallelism is a Good Thing" camp, but the counter argument to your point is that having a larger set of concurrency abstractions is a Bad Thing in that any particular piece of code has to consider all of the different permutations. In a shared-nothing world, there's a lot less to worry about (except occasionally performance).
- vvanders 7y agoThe world writeable cross thread also has implications on how your GC algorithm is designed. Erlang for instance scopes gc pools per process so short lived processes just drop the pool. Also GC of one worker doesn't stop any others. Can't remember if it even needs to be generational because the heaps are already sliced by process. It's the closest thing to heap arenas I've seen in a VM based language. Or take Lua which is single threaded and doesn't require VM safepoints since everything is done via cooperative coroutines. Java needs to assume worst case and as such has to be conservative in some of it's approaches.
- deleted 7y ago[deleted]
- mrkeen 7y ago... what are they?
- bsder 7y agohttps://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html https://docs.oracle.com/javase/8/docs/api/java/util/concurre... And given that you didn't know that, you really need to study them. java.util.concurrent is one of the greatest gems of software ever written.
- mrkeen 7y agoSo I describe the shortcomings of CompletableFutures, and you point out that there's a java.util.concurrent package? Is this method one of its gems? A cancel() which doesn't cancel? https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#cancel-boolean- https://docs.oracle.com/javase/8/docs/api/java/util/concurre... > Synchronized primitives don't compose. You can safely `synchronized get(...)` and safely `synchronized put(...)`. But their composition put(get(...)+1) isn't synchronized. So is there anything in java.util.concurrent that does compose? put(get()) has exactly the same problem up here at the 'high level' (of CountdownLatches and Semaphores) as it does at the 'low level' (of synchronized methods.)
- lenkite 7y agoWhat do you mean the cancel method doesn't cancel ? It does cancel with a CancellationException stored in the future and an optional interrupt send to the thread running the blocking operation.
- mrkeen 7y ago> What do you mean the cancel method doesn't cancel? Try it. @Test public void cannotCancelARunningFuture() { // Future that just sleeps CompletableFuture<Void> sleeping = CompletableFuture.supplyAsync(() -> { int i = 0; while (true) { System.out.println("zzzz: " + i++); threadSleep(300); } }); // Make sure it started threadSleep(1000); sleeping.cancel(true); System.out.println("Sleep was cancelled"); threadSleep(1000); System.out.println("Haha no it wasn't"); } =============================== zzzz: 0 zzzz: 1 zzzz: 2 zzzz: 3 Sleep was cancelled zzzz: 4 zzzz: 5 zzzz: 6 Haha no it wasn't
- kimi 7y agoAs written here: https://github.com/l3nz/SlicedBread https://github.com/l3nz/SlicedBread - "the over 400 rich pages of "Java concurrency in practice" show how hard it is to write and debug a good-mannered multithreaded application in standard Java."
- vips7L 7y agoHow can't a CF be cancelled? Since JDK8: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#cancel-boolean- https://docs.oracle.com/javase/8/docs/api/java/util/concurre...
- mrkeen 7y ago> > A CF can't decide to sleep for a while, nor can it be cancelled. > How can't a CF be cancelled? So glad you brought up the docs. CF implements cancel(boolean mayInterruptIfRunning)... which does nothing ;) More precisely, it will not cancel a running CF. If the CF hasn't started yet, by all means cancel it. But if it's running, that cancel method does nothing.
- eggsnbacon1 7y agooriginal Futures can't be cancelled. CompleteableFuture can be, but only if the thread agrees to die. You can achieve arbitrary non-blocking delays by using the cruft scheduled thread executor or doing it sanely with RxJava. Really its just dangerous to do nonblocking stuff in Java without a wrapper like RxJava. That's not a good thing, I look forward to the day there's real fibers