Concurrency problem in entity updates

Hi guys,
I’m developing a little mmorpg and I’m stuck with this problem: I had multiple server nodes (threads) handling different map regions, the nodes received packets from the network and proccessed them to update the game, I had a queue for incoming packet and every update tick a packet was processed, every UNDEFINED_NUMBER of ticks I performed the region update (mob movemente, mob attacks etc)

But I thought it wasn’t a good idea to stop the packet processing with a big regionUpdate() method so I created two different thread:
-regionUpdater, which only performs region updates every tot of milliseconds (6-7 times a second maybe)
-regionHandler, which still processes incoming packets

But now the problem is: if the regionUpdater is updating player1’s health and the regionHandler receives a packet that contains information about the player1’s health (maybe he’s been attacked) I have a consistency problem with that player.

Have you got any solution for this? Maybe I have to go back to the design phase :frowning: Have you got any better idea for my design?

Why not build in an action buffer for each interactable object so that when this happens you put a heal and a damage into the buffer.

Can you better explain this solution, please? I’m sorry but I didn’t get it :clue:

Code? Most likely removing item while in loop.

Better explanation would help…

If this is actually how you want to do it, then it’s simply a synchronization problem. Have the information behind some kind of mutex to restrict access to one thread at a time.

Isn’t there a better approach? :confused:

If more than one thread access shared data, and at least one of them may be modifying the data, then there must be synchronization of some kind.
The only way to not have to use synchronization is to not satisfy those conditions (e.g. by using immutable data, thread-local data, or only using one thread, etc.), which is a design issue.

Simple solution is not do do mmorpg’s.

Yeash , burnt pizza just went a whole shade of green!

Wow I answered this on my phone. All the post said was “bump.” I’m confused.

Use
synchronized(packetslist) {
//Health handling
}
synchronized(packetslist) {
//packet reading
}

you could just replace your collections :

depends on how you store your stuff :

a http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html which is a Queue …
a http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedDeque.html which is a Deque …
a http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html which is a Map …
a http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentSkipListSet.html which is a Set …

a CopyOnWriteArrayList might be too expensive when used alot.

anway, this is not the best solution but the easiest. no need to worry about synchronised or modification-exceptions.

but keep in mind : if you use those collections, never trust them! when more threads read and write to a collection, whenever you query a element or property (size() etc.), results are just valid when executed. the next line in your code, state can be invalid already. (this is where Locks and synchronized() comes in handy).

Using synchronized blocks is one way, and is a quick and easy. There is a performance penalty to doing this which can be small, or can be large, depending on implementation.

Another method relating to Concurrent Collections is to have the network (regionHandler thread) post a message/command/update object to the main thread to be processed later by the regionUpdater thread. JME3 implements this method by having an the enqueue method on Application :

 public <V> Future<V> enqueue(Callable<V> callable)

Where Callable is a Java interface that has a single method : call. It allows you to return a type, but in this case it doesn’t really matter. Simple create an anonymous inner type to do a simple task like update HP and then return null (or type the Callable to return Void).

An implementation for your case might look something like this:


public void recieveHpUpdate(int newHp, int entityId) {
		this.mainUpdateObject.enqueue(new Callable<Void>() {

			@Override
			public Void call() throws Exception {
				actuallySetEntityHp(newHp, entityId);
			}
		});
	}