Without a mutex, you can’t even write code equivalent to that in the article because you cant mutably share as you pointed out. With a mutex you could – and the mutex would prevent data races (but not race conditions in general) – but indeed mutexes are a red herring here (at least in the specific sense of a runtime synchronization primitive).
In Java you can’t synchronize defensively because synchronization requires that everybody who has access to the shared resource cooperates with you. And even if you could, you wouldn’t want to, not in this sort of a case.
In Rust mutexes own the data they protect, and make it impossible for anyone to access the data without locking the mutex first, but again, an API like this would clearly not bother with dealing with mutexes but rather take a normal compile-time-checked borrow.