|
In Erlang processes need to send messages to each other. And those messages are copies (nothing is shared). This is less efficient than in Java where everything is shared, but it also means that process a cannot change something that process b is looking at. So locks in Erlang, aren't necessary. It also enables easy distribution. When all processes share data by messaging, it doesn't matter if those processes are running on the same machine or are distributed on a network. Since Erlang has one GC per process, you can create garbage in one process without triggering GC if that process is short lived. Once the process dies, the entire heap for that process is returned to memory. So in Java, you'd have to write code in a special way to avoid GC, but in Erlang that happens automatically if either your process exits before the heap for that process needs GC. And in Erlang it's pretty normal to run one process per http request, so this does happen in practice, without requiring anything of the programmer. When it comes to hot code reloading and data migration. When you hot load code into an Erlang vm, a hook will be called if defined which allows you to migrate all data that is in memory into new format. So, you're not restricted by data-incompatibility. Your last paragraph is what I referred to by required discipline. Everyone that touches the code is required to understand what causes corruption and what doesn't. It also requires that you know which classes are thread safe and which arent, which is hopefully documented somewhere. Thread groups need to be understood (I work in Java/Kotlin every day, and I didn't know what thread groups were before today). In Erlang, data corruption due to multiple processes doesn't happen, and grouping processes together (supervision trees) is so common I can't remember the last time I saw an Erlang program without one. Which of course doesn't mean that Erlang is superior to Java. But when you're working on something highly concurrent which needs to be fault tolerant, I'd argue that you'd get a better result with less effort than in Java. But of course, if you know Java really well and don't know Erlang at all, YMMW. |
Erlang's model with fibers and message passing sounds close to Golang. Java has decent support for immutable objects with immutable collections, Lombok, the FreeBuilder library, both build-time code generators, and Java 14 record types. Automatic passing between machines is unique to Erlang
Per process GC isn't anything like Java does, but the new GC's are probably fast enough that it doesn't matter in practice. For any sane sized heaps the GC pauses are around 0.5 millisecond. This wasn't true until a few years ago, and in production most people don't know or care enough to use the new GC's.
You are right about thread safety in objects. Thankfully the JDK surface is fully documented. Third party libraries usually are. Internal code is a crapshoot. It requires discipline, but I still find it rare in practice because the normal patterns lend themselves to thread safety.
I think its safe to say that Java is a lower level language than Erlang which enables many of the same patterns with less convenience. You can probably get better performance with Java, but your fault tolerance completely depends on how good your coders are. Java will not save you from doing stupid things between threads.