15 ms·
People always used to ask me for advice on multithreading, because I had a reputation for multithreaded code that worked. I recommended they use Retlang (there'
by moomin 9y ago
People always used to ask me for advice on multithreading, because I had a reputation for multithreaded code that worked. I recommended they use Retlang (there's a Java version called Jetlang), which works on a shared-nothing message passing basis (and is blindingly fast). They tended to say they didn't want a library and just wanted to use locks and threads. I said that not doing that was how come I had a reputation for correctness.
- bsder 9y agoThey're in Java and writing locks and threads. Sigh. java.util.concurrent is probably the single best concurrency library I have ever used. Bar none. When I'm writing in Java, and I find myself writing a lock, my first reaction now is: "This is okay for exploration, but which data structure from java.util.concurrent am I going to have swap in here when it's all done. And can I do it now and save myself a lot of grief." It only took me 7+ years to come to this realization. Apparently I'm a slow learner. :(
- 2sk21 9y agoMy small brush with this: back in the summer of 1990, I did a summer internship with Doug Lea who led the JSR 166 group that led to java.util.concurrent. My work was on a concurrency library for a parallel computer called the Encore Multimax
- MrBuddyCasino 9y ago> summer of 1990 some thread corrupted this date
- cup-of-tea 9y agoThey're using Java instead of Clojure. Sigh.
- joncampbelldev 9y agoI'm saying this as a massive clojure fanboy: java.util.concurrent is an amazing set of concurrency utilities and is the building block for many of clojure's concurrency features. It's definitely worth knowing when writing performant java AND clojure (you can wrap the little bit you need so you don't have to scatter java interop all over your codebase). Sometimes a (swap! atom fn) doesn't cut it.
- peterashford 9y agoYeah, because some of the best concurrency primitives in the world aren't quite "what teh cool kids are doin'"
- jnordwick 9y ago> "This is okay for exploration, but which data structure from java.util.concurrent am I going to have swap in here when it's all done. That just doesn't work for most concurrent code. Often you have dependencies between data structures or other operations intervening. Most of the time it isn't a single structure, but a group of semantic operations across the program.
- chopin 9y agoThe main problem with Java is that you rely heavily on libraries and frameworks which may or may not enable you to apply a desired pattern. Recent example: I am using Tomcat as a servlet engine. For dependency injection I am using JNDI. Tomcat can be configured to call a provided ObjectFactory to generate JNDI objects when they are requested. The environment I am using allows for some kind of blue-green deployment, I can switch between different fired up virtual machines transparently to users. I use this when upgrading. My provided Objectfactory logs when objects are created (some of them should be strictly singletons). Sometimes the logs indicated that multiple objects where created after switching to the newly updated machine. This was due to a high load on the system in which multiple threads where busy with incoming requests simultaneously. Neither the language library nor Tomcat has any safeguards in place (synchronization of any sort) although JNDI and in particular Tomcat supports singleton creation. I had to resort to statically creating the required instances at loading the Objectfactory, a pattern I dislike with a passion (you can't swap the implementation during runtime which can be annyoing in any long-running environment).
- peterashford 9y agoTo be fair, that's more an issue of using a framework than anything to do with Java.
- laythea 9y ago(shared-nothing = copy-everything != blazingly fast)? also: (multi-threading + shared-nothing) = much less complexity = more correctness
- fsloth 9y ago"shared-nothing = copy-everything != blazingly fast)?" Not OP, but, if that does not give you more speed I'm not sure your problem should be multithreaded in the first place. Threads themselves are not free, there is a non-trivial cost in switching thread context. Trying to use multiple threads to wiggle the same memory area is insanity in most cases however you look it.
- yzmtf2008 9y agoAn example where it's not insanity (while it might seem to be): https://arxiv.org/abs/1106.5730 https://arxiv.org/abs/1106.5730
- chacham15 9y agoI dont think this is true. The first example that came to my mind was a database. Shared-nothing + copy-everything is a very bad idea there and it is a thing that definitely needs to be multithreaded for performance.
- hiram112 9y agoComment if you can: We've got an app that is pretty slow. Partially the fault of the front-end doing a lot of synchronous promises. But on the backend we have a lot of calls where we are getting a list off foos from the DB, then spinning through for loops and making one or two synchronous calls to other microseconds to fill in the details. I hated algorithms - but this is O(n^2) and we could cut it down to 2n -> O(n) by spinning off the fir loop to futures. This is java using completable futures with whatever thread pool the generic executor creates. Any issues?
- moomin 9y agoMake the messages immutable. Then the message passing is blazingly fast. You can argue about whether that’s strictly “shared-nothing” but practically it works. Ofc, in Rust you can safely send mutable messages and transfer ownership.
- jcrites 9y agoI agree that you shouldn't be touching locks and threads, typically. However, I think you can get pretty far these days with just the built-in Java class library, using features like Futures (CompletableFuture), ExecutorService, ForkJoinPool, and BlockingQueue and such. Before CompletableFuture there was Guava's ListenableFuture. Synchronized methods are also useful in certain situations. I've built several fairly sophisticated concurrent applications using these primitives and felt they worked out reasonably well. I find that BlockingQueues with thread-pool-backed ExecutorServices provide a model that's fairly robust while being simple to reason about and monitor.
- bunderbunder 9y agoI'd go one further and suggest, "don't". It's not just about safety, it's also about frequently not even needing it. I've achieved some pretty tidy code simplifications without harming the performance of the overall application by removing unnecessary multithreading. I've even sometimes achieved some pretty tidy performance increases while simultaneously simplifying the code by removing unnecessary multithreading.
- yazan94 9y agoCan you explain at a high level the type of work the second app you mentioned was doing? I know that multithreading actually causes slowdowns if the task each thread isn't substantial enough to offset the context-switching and if the tasks are dependent/interconnected. Are there any other criteria to take into account when considering whether or not to make an app multithreaded?
- bunderbunder 9y agoPretty much that. It's not just the context switching, it's that it can be tricky to come up with a synchronization strategy that doesn't confound the CPU scheduler's efforts to keep the pipeline full. It also depends on your environment. That 2nd app I mentioned was running on physical hardware that was running many applications. In that kind of environment, you can end up in a sort of, "double your CPU cores, double your cache misses" situation. And the performance story ends up not just being about one little module; it's about the entire system. There can be a sort of performance prisoner's dilemma, where trying to individually maximize the performance of every single piece in isolation actually results in slower overall performance.
- oconnore 9y agoThis is not a helpful suggestion (even if it's often correct) in the same way that "don't get a knee replacement" is also unhelpful (though often correct).
- bunderbunder 9y agoHeh. Coincidentally, I've got a bad knee. "Don't get a knee surgery" was one of the most helpful things my doctor told me. When you're surrounded by people who (with good intentions) advocate fiddling with things, there's a lot of value in also having someone to argue for a more moderate approach.