As I understand from the source code, (socket_tcp, at least) socket send / recv comes down to erlang: port_command for send and erlang: port_control for recv on the socket port (see prim_inet.erl).
For port_command: "if the port is busy, the call process will be suspended until the port is busy." Port_control is also a synchronous operation.
Correct me if I am wrong, but it would be completely safe to use several processes to read and write to the socket.