I am having the same dilemma on my flex application.
It seems that best way to deal with this is to keep an interval of some seconds between server and client, and force polling the state to each clients.
I have made the following approach, note that this does not solve the out of sync situation, it just reduces significantly the possible situation to happen.
I have at server side, one cache of each collection calls.
I have at client side, per instance of application, one cache of that same collections.
Instance one loads some array of objects into a grid. (Builds a collection initial state with the server)
Instance two loads and makes changes, submitting changed data to the server, db info is persisted and server cache is rebuilt.
(Client cache also maintains its local cache not requiring to call for the server collection again.)
Instance one is out of sync. (will be in sync at the next polling interval)
instance two is sync due to being the app responsible for the changes.
Both instances polls the server from time to time, like a 10 second interval for changes.
(If server side cache suffered changes, it will bring the new info to all clients on next interval call.)
If no changes at server side level, no info is sent to one already registered client.
(This means no info is exchanged between server and client, reducing overhead.)
If a third client comes in, it's state is fresh and will perform the necessary calls to build its current cache as well.
There is a delay, but it surely helps out propagating changes to the client.
The problem is that the client consumes some extra memory by keeping it's cache state.
I am doing this in a per screen situation, once that screen is out of view, the client cache is nulled, once that screen is called again, local cache is created and the timer starts and the polling begins.
Hope that helps,
Ernani