When you expect this to happen (and chances that you forget about it are high) you can solve it with a lock. Adding a lock to the data means that one thread has to wait with reading or manipulating a piece of data until the other thread is finished.
But using locks can cause another problem: Deadlocks!
In my server I have currently two kinds of objects which have threads: ClientConnection and MapInstance. The client connection is unlikely to have problems, because the thread is only sending data to other threads, not receiving from them. Receiving data is a synchronous process. By declaring the send method as synchronized I won't have to worry about messages mixing up when multiple threads try to send data to the client at the same time.
But the map instances are a more serious problem. Their data is manipulated by a bunch of controllers they own (currently only one, but more are about to come). I am glad that processing inside the MapInstance class is single-threaded, because the controllers are processed in order and they are not supposed to communicate with the outer world except through the MapInstance class. But at any time during processing, the maps MessageDispatcher can receive a message from another thread, which is immediately passed to the controllers, which could currently be inside of their processing loop.
To prevent this from happening I could:
A) When the MessageDisptcher is delivering a message to a controller, make it check the controller if it is currently busy and when it is wait for it to finish before delivering the message. But this might cause serious delays or even deadlocks in message processing.
B) separate receiving messages from processing messages in the controllers. That way a controller can store a message but don't actually do anything with it until its update method is called. At the beginning of its update, every controller should:
- Lock its message queue
- Copy its message queue into a buffer
- Unlock its message queue
- Process the buffered queue
Then I just have to make sure that controllers don't communicate with the outside world except through the message queue.
No comments:
Post a Comment