The design decision of providing thread safe operations on data structures by default is a pretty poor one. In my experience this is the wrong level of abstraction on which to perform mutual exclusion of certain operations. Normally you want locks around a transaction-like operation that might involve multiple operations on a data structure (or multiple data structures). When just using concurrency safe containers on their own, subtle consistency bugs can be introduced and you end up writing a second layer of locks around the higher level code anyways, now paying the performance overhead of locking twice, once for your logic and then for the container.
I agree, while 'lock data not code' sounds good(that's what Rust does I think), container is a different story, it's by design mutable and unfit to lock as a data structure, container is not a pure data structure, it's a ADT that really works with data structure and its methods(algorithms) hands in hands, hard to split by any lock.