
A landmark book describing a process algebra (Communicating Sequential Processes, or CSP) for designing algorithms that exploit concurrency and communication.
I also wrote a blog post a while back when I did a talk at work, it's Go focused but still worth the read I think.
[0] https://bognov.tech/communicating-sequential-processes-in-go...
https://www.cs.cmu.edu/~crary/819-f09/Hoare78.pdf
Both Erlang and Go use this model. As @duped stated, Rust uses a different model
However, concurrency is much more than IO. Concurrency can be best defined as a lack of ordering of computation. For example, you want to compute A, B, C and their values are independent of each other, the order you compute them does not matter - that is concurrency. If your language has means of expressing "compute these things, i dont care about the order", then your language supports concurrency.
I suggest reading Communicating Sequential Processes by Tony Hoare. It is a very influential work on concurrency - and the proof of its influence is the design of the Go programming language.