If I might try to elucidate what Butcher explained, the Actor model used by Erlang/Elixir was supposed to be a "purer" object-oriented programming model that defined how objects passed information between each other rather than the state and attributes of an object, and it worked well concurrently because objects don't share state outside of messages. However, actors are expensive because they tightly couple an object (the transport object) with a process (the mode of communication) unnecessarily.
CSP improves on this model by decoupling objects and processes. It eliminates the need for a process and defines a "routine" instead as a state machine for an imperative code segment, and in doing so creates a one-to-many relationship between a given routine and the hardware-defined threadpool. Buffer objects on a given routine and only exlicitly block when you need to. When an imperative segment of code is blocked in a routine, the routine relinquishes control of the underlying thread while managing state, and when it is unblocked, can begin executing on perhaps another thread with the given state. So it's easier to make imperative code concurrent. State machines are also much cheaper to create than an actual process. CSP is highly effective running concurrent tasks that may have lots of blocking events, such as tasks issued through network, which may be why a lot of the newer network-centric libraries like Kubernetes are written in a CSP-first language like Golang.
I'd definitely buy the book, I've learned a lot (never understood why Golang was so popular until now): https://pragprog.com/book/pb7con/seven-concurrency-models-in...