Indeed.
The other option is to maintain 'shadow state' where by objects have a 'public' copy of data (likely a subset of internal state); anyone is free to read from it and the objects only update their internal state. At a predefined point in time all objects copy 'live' to 'shadow'.
Yes, all your reads are one frame behind but for most things this is unlikely to make a huge difference and removes any and all locks from the system. This is probably best expressed in 'tasks'.
Yeah, I actually use shadow states myself but I still use the barrier solution for "system" update separation, I just figured the outline was a nice simple example of the different method of looking at things. Anyway, the better example would be move all the objects in one shot using shadows, barrier, apply all shadows, barrier, update sweep/prune awareness system, culling, and anything else not interdependent, barrier, issue rendering etc etc. You still need the concept of the barrier to separate those updates when appropriate but it is still a massive reduction in locking/blocking.
As to the "task" system, I have a different way to look at it. Some items distribute differently than others, so I supply a generic concept of "distributor" which will simply be called by all threads in the team. So, an object update distributor simply divides up the updates to be called among all threads and lets them go to town, it doesn't care if they come back at different rates and there is no blocking, just one atomic to track which sections of the array have been issued to each thread. Threads come out and start executing the next distributor which in the outline would be a barrier since we want to make sure all objects are updated prior to applying the shadows. (Assuming the tasks are side by side as in the example.) On the other hand, I have a sweep prune awareness system which is currently only multicored enough to use 3 threads right now, so that uses a custom distributor which grabs the first three threads which enter and lets all the remaining ones pass through, those threads could go onto say update the scene graph/culling since it is not reliant on the sweep prune nor affected by it so they end up running in parallel.
As to the reads being a frame behind, I prefer it that way since it is a consistent guarantee which can be made and at worst if you absolutely have to be looking at "now" you can just extrapolate 1 approx frame ahead which is usually fairly accurate at such a fine grain delta. Order issues in object dependencies is always a nightmare in traditional game loops, that object updated first but depended on this object, next frame they may be reversed and you end up with nasty little oscillations in things like a follow state.