Coming from a shared memory mutable objects world (java / ruby), understanding how erlang is dealing with concurrency was quite interesting to me. Here is what I found
In Erlang world all the objects are immutable. Meaning, once an object is created, it is not going to change. If you wanted to change it what you will get is another object but never the already created object is changed. Well, if you are thinking that it is not very efficient, the VM does use some tricks to keep it fast.
For Example, When you create a collection and add an item to it, a new collection is not created everytime.
An erlang process is a light weight unit of code execution and a single thread runs multiple processes preemptively. This means, every process will be given time to run and will be suspended based on multiple conditions like IO block request or a specific count of methods called. So, a single thread can run huge number of processes.
Each process has a private stack, heap and shared heap (for big objects) and the garbage collection runs per process. You can read more about the garbage collector here
There is no shared memory between the processes in erlang. This means, the VM does not need to worry about the same object being accessed across processes. The object is copied from one process to another if it is passed across
Erlang took an approach to not share memory across processes and kept it easy to swap out and in of execution to make it crazy parallel. Its per processes garbage collector design also leads to no stop the world GC that will lead to unexpected delays across the processes