Each shared_ptr to an object shares a control block containing the reference count. Copying a shared_ptr increments the count atomically. Destroying one decrements it atomically. Atomic operations make shared_ptr thread-safe for the count itself.
Multiple threads can copy and destroy shared_ptrs to the same object. The object access still needs synchronization. Reference counting has overhead: the control block memory and atomic operations.
This is why unique_ptr is preferred when you don't need sharing. Use shared_ptr only when necessary.