Hi Nico, I know what question you are asking as I have had similar situations in my own experience, but the config_db is not the place where this problem is intended to be resolved.
In fact, I recommend you use the config_db just once, to pass a handle to a config object that you define, containing whichever fields and access methods you need (or even containing whole models, register models, any shared 'state' that may be referred to by your scoreboards, sequences, other components. You can then deal with any application-specific requirements for synchronization by coding access methods within the config object on a case by case basis.
A lot of the race conditions are avoided though by a synchronous approach: if your monitor is synchronous to the protocol clock, then it will only call write() on the analysis port synchronously, and the scoreboard connected to that analysis port (which refers to and updates a config object, say) will do those accesses synchronously. So other components would have a predefined access model controlled directly from your DUT protocol clock. In my experience this removes the need of 90% of all synchronization worries. The other 10% can use semaphores or other access methods.
So I would say, this is not a problem, and is one other reason to use the config_db with objects, not just discrete ints etc. [if the performance overhead is not enough of a reason already]
Interesting topic, yes we can say more about this in the cookbook.