Locking object hierarchy in .NET.

I have a class that represents "state of the world". The class has many collections of many other objects, which in turn have references to more objects and collections of objects, sometimes even references to their ancestors in the "world hierarchy". To keep things simple, here's an example (converted to XML, details omitted):

<World>
<Country>
    <City>
        <Block>
        ...
        </Block>
    </City>
    <City>
        <Block>
        ...
        </Block>
    </City>
</Country>
...
<Country>
    <City>
        <Block> ... </Block>
        ...
        <Block> ... </Block>
    </City>
    <City>
        <Block> ... </Block>
    </City>
</Country>
</World>

      

There are two threads: the UI thread and the background thread (which is actually the server).

The server receives messages that change the "state of the world" (adding cities, blocks, etc.).

The UI thread draws the world state for display using a PictureBox once in a while. The view layer only contains a reference to the IWorld object (which World implements) and it does not have access to the elements inside.

The UI thread must block the complete state of the world so that the world cannot be changed (by the server) while drawing (which would make an inconsistent picture of the world). Since it only has a reference to the IWorld object, that's the only thing to block.

My question is whether this locking is sufficient (i.e. locking all fields and properties that this object has recursively) or should each object be locked separately. What is the correct approach to this problem?

Note: The UI has no way of communicating with the server (which means it can't tell the server to stop changing the world and then tell it to resume after rendering).

EDIT : If World and all classes in the hierarchy implement the ILock interface, which provides a Lock () method that will call Lock () at all lower levels (recursively), this is likely to be deadlocked (circular references) or just too costly ...

I assume the design change is ok.

+2


source to share


2 answers


You don't need to block recursively - if both threads just block on the same reference IWorld

, that will be enough to ensure mutual exclusivity.

Locking individual items would give you finer locking, but then you might get an inconsistent picture - I would assume that you want to see a whole set of changes from the server at a time.



However, a better model would usually be to force the server to publish "snapshots" and then create a new copy of the world and modify the copy to turn it into a snapshot when needed. This way you don't need this mutual exclusion that can block your UI when it wants to draw the world while the server is changing it.

+3


source


The main question is how do you access the elements underground. If everything is available through the "World Singleton" then the global lock will be fine and safe.
If you are accessing countries, cities, etc. directly, you need separate locks that need to be requested in the same order if you need to change multiple parts of the chain at the same time.



+1


source







All Articles