0

In the Model View Controller (or Model View View-Controller) design pattern, it is common to have separate threads for the data source and the UI. For example, lets say the app in question is a Bluetooth LE thermometer reader. The natural thing would be to have one thread getting data asynchronously from that thermometer while the UI thread updates the readings on the screen.

Now picture an app that can pull data from a bunch of thermometers. It makes sense to wrap things like Temperature and Battery Level into a class and have each connected device as a new instance of that Thermometer class. But since the data is arriving at each device asynchronously from the Bluetooth device, it is possible for the UI thread to read a property of a Thermometer while the value is being updated.

So in general, it seems to me that if you have a data source on a different thread than the business logic, every single accessor (get, set, etc.) should utilize lock. Is this true? Or is there some thread safety built into public accessors? If not, then implementing a lock on every single get/set method seems incredibly tedious and not to mention inefficient for large data sources.

  • Lock in individual properties is almost always wrong as it does not guarantee consistency of data. You need to think what "piece of data" means in your app and make sure every time your access on it is done in consistent manner. Note that using immutable data structures makes thinking about multithreaded code *easier* (not easy) as once created such objects won't change and hence always consistent and thread safe. – Alexei Levenkov Mar 06 '16 at 21:53

1 Answers1

0

Not an expert on MVC but lets have a look at your example. As you correctly identified, your Model is a class or a structure that holds the thermometer data - called Thermometer. Your controller is the runnable/thread that polls the device for data, has a Thermometer instance and is responsible for updating it (I 'll call it TemperatureProvider). Your View is getting data from the controllers and generates what is to be rendered on the UI. So far so good, to the questions:

it is possible for the UI thread to read a property of a Thermometer while the value is being updated.

Yes it is, but you might be able to get away with it see this for read operations. It is however suggested to use mutexes in multi-thread environments. For write operations, you definitely need locking if more than one threads can write at the same time, which brings as to the next question:

Or is there some thread safety built into public accessors?

Nope, not that I know of... You have to implement locking yourself. However, looking at your example, I can see two ways of implementing it, depending on the architecture:

  1. As you suggest, you can build it in the model/Thermometer in which case the getters/setters will implement some sort of RW locking. This assumes that only one Thermometer instance exists per-device

  2. Assuming that your application has access to N TemperatureProviders, one for each device, then you could implement the locking in the controller. I tend to prefer this approach because it leaves the data structure intact and keeps it simple. Additionally, it allows you to reuse this structure in different context, for example, a list/hash of timestamp => Temperature with historic data which needs no RW locking.

Now moving on to something a bit different: You can build your software in such a way that you do not require your main thread or UI to poll the controllers. As far as I understand the MVC model, these approaches do not break it:

  1. Decouple completely the device poller from the UI/View by using an intermediate storage stage (which will also handle locking) like a database. In this case your TemperatureProviders are updating a table, while the view is querying it. They both use the same model (Thermometer) to transfer and store data but have different instances.

  2. Use the observer pattern (a.k.a. listeners or push/publish). In this case, instead of the UI polling the controllers, the controllers are "updating"/"notifying" the UI. You can see lots of examples of this approach in Java (the most common being the ActionListener).

  3. Depending on the application, sometimes a Queue is very useful for transferring messages. Most languages provide a thread safe queue implementation ready for use. This way you don't have to implement locking. In your example you could have a queue in the main thread and each controller will push new values when received. The main thread will only have to check the queue for new measurements.

If your question is for a real application (and not a theoretical one) I would suggest that you go with the observer pattern (but that's mainly opinion based).

Hope I didn't bore you :)

PS: My terminology might not be from C# but other languages...

Community
  • 1
  • 1
urban
  • 5,392
  • 3
  • 19
  • 45