I have only recently been studying Elixir and I hear about how simple it is to work with concurrency in the language. Does this mean that we don’t have to deal with race conditions, deadlocks and other problems? Doesn’t that make me know less about concurrency ?
In addition to the other points made, because the model for exchanging concurrent data is always explicit it is often the case that it is easier to see that a particular implementation will lead to race conditions or dead locks.
Elixir uses Erlang VM called BEAM uses processes (actors) that communicate with other processes by message passing and I’ll be calling them actors in rest of this answer.
You can still get race conditions
actor1 keeps state
actor2 and actor3 send message to actor1 that changes state at “same” time
actor4 ask actor1 for state and that state could be state set by actor2 or actor3
But all in all in Elixir’s actor model it’s much simpler to reason about and you don’t usually have same kind concurrency problems you have in other languages. Because actor is running “single threaded” from programmers point of view and have their own memory that other actors can’t access. They communicate with other actors by sending them messages.
So you are still thinking about it but differently.
Race conditions: no. There is nothing that can guard you against race conditions. I would say that vm startup race conditions bite me in the butt once every few months (but I’m really good at recognizing them now, and they are easy to fix in elixir).
Deadlocks: It’s rather hard to write a deadlock in elixir. At least genserver will keep you from writing a call from a process to itself. You could deadlock by calling a process that calls back, but that’s maybe a sign of poor systems design… So I can totally see a noob, especially from oop-land doing this.
Honestly, if anything you’ll get much better at writing correct concurrency patterns because a lot of the boilerplate will be pushed out of the way freeing you to think about the truly hard things like consistency, resiliency, and fault tolerance. In most other concurrent-capable PLs, I’m so exhausted with boilerplate that I can’t bother to think about those issues.
Recently I started implementing code in multithreaded zig and I realized that having worked in elixir “doing the right thing” just came naturally.