For a reasonable amount of locking, The Arc / RwLock dance offers good performance (other languages, like Swift, use something like Arc for every property access (although the compiler tries to optimise it away)).
The safety is actually better because you're forced to think about the failure case. I don't have good memories of Objective-C where some Foundation calls don't throw (in they don't have an error parameter), but just throw random undocumented exceptions. (Not saying that some Rust calls don't panic, but knowing that something can go wrong is much better than learning about it in production).
Which is to say, accessing a client may or may not be thread safe (depending on the client implementation) but assuming it’s not a multiplexing client, it almost certainly uses some kind of locking mechanism under the hood
Even if it is a multiplexing client, if you saturate the internal clients you will either need to wait for a client to stop writing to its socket (through perhaps a lockless consumer model) or create a new internal client (slow).
Concurrency problems don't magically disappear because your language can check for them. You still need to use memory-safe patterns, but the compiler will force your hand and prevent you from doing unsafe things accidentally.
In the end, this makes it far easier to build correct, concurrent applications. If you decide to try some fancy new pattern that doesn't require locking, the compiler can guarantee the memory safety of your new implementation.