Multithreaded Observer

Asked by At

I'm writing kind of multithreading observer and i encounter some design issue.

Let's say i have some kind of thread pool with queue of tasks to perform on dataset. Some of them are read data only, others override them.

After a change in data, i want to perform notifyall(), so observers can update() their state.

The threads that perform update() task, i want them to be from a different, second thread pool.

And there is a problem: how to force all update() threads to perform their update operation, before another function from first queue of tasks start to modify the data?

I'm thinking about something like passing lock to another, specific thread.

1 Answers

0
Community On

If you can, avoid using locks. This will defeat the purpose of having multiple threads doing work in parallel. If you need to call update on another thread because you are required to by your framework (GUI thread for example), locks will cause blocking on the UI thread and will kill your performance.

Specific solutions will depend on specific situations. You need to give a concrete example so a concrete solution can be given.

The best way is to not use shared objects at all. Have one thread publish immutable events to a queue that the other thread can read and update based on these events.

If you need to use shared objects, in order to be able to read the state of an object in a point in time, you can use Memento to create a snapshot of an object that can be read from the second thread.

If you need to get all changes from the second thread you can keep a history of changes in your data objects, so that the udpate() thread can keep track of where it is and can read new changes as it receives change notifications.

If you don't need history just keep the last change. The update thread may skip some changes, but in the end it will be consistent with the data when it processes the last thread. You are using multithreading, so there is not way to always be consistent.

Check this article. The LMAX team uses different thread by having only one thread for their BusinessLogic. One thread receives events and put's them in a buffer. The other thread, the BusinessLogic thread with the EventProcessor picks them up and processes them. Their solution works in the situations where you have a single writer multiple reader and every reader can keep track of where it is in the buffer. In your case if you have only two threads, you can do something like this.

You can also use the Actor model where you have multiple concurrent actors that work together by sending messages between them.