Maybe I misunderstood. I took the first bullet to refer to wrapping operations in a lock and the second to refer to single writer multiple reader.
At least in the single writer scenario it all breaks down if a lock free reader requires multiple items that are related to one another. It's an easy oversight to make though.
Fixing it sucks because you usually have to go and add locking to your previously fast and efficient lock free setup.
> At least in the single writer scenario it all breaks down if a lock free reader requires multiple items that are related to one another. It's an easy oversight to make though.
This is true -- generally the solution to this is to ask for everything in a single message.
It can also break if the read implementation has mutable side effects, e.g. rebalancing. Java HashMap used to have this causing an infinite loop. I haven’t looked recently but my guess is it still does.
I mean, that's the "art of the deal". If you have a lock for all eternity, then you have a single owner, and are practically single-threaded.
The hard part is exactly all the combinations locks can be hold and given up, which will have a non-trivial number for more complex programs/data structures. That's where modeling software can help by iterating over all the possible cases.
That can still break if a reader makes multiple calls and implicitly assumes that the data structure at large hasn't been mutated between them.