если в момент чтения того или иного свойства происходит обновление или удаление, то я должен оборачивать в блокировку режима чтения каждое поле/свойство?
Что-то это уже не похоже на кэш. Может быть, когда изменяется объект, то из кэша убирать его _после_ изменения. Тогда последующие потоки получат верный объект. А операции добавления и удаления в ConcurrentDictionary потокобезопасны. Т.е. идея в том чтобы не изменять объект в кэше никогда, а только удалять и добавлять.
Существует смежная проблема: поля в некоторых сущностях являются списками ...
Ну, теже ConcurrentQueue, СoncurrentStack поддерживают GetEnumerable, который делает копию всего списка. Тогда не страшно, что кто-то изменит список.
Тогда можно без сторонних библиотек обойтись. Вообще, сложно что-то сказать конкретно без кода.