This applies to C (and probably to any other similar non-object oriented language). If I have a central data store and potentially concurrent access there are two ways I can see of protecting it.Let's say I have a data store with a few data elements...struct MyStore{    int data1, data2, data3, ...., dataN;} store[M];In this example the data types are the same but let's imagine this applies to something a bit more varied with different types etc... this is just to keep the question simple.To grant other users access to the data within I could do a few things.Could provide critical region functions and rely on the caller to get the protection correct.I could provide a setter and getter function for each data item type in the store and manage the critical regions within the module and protect the user from having to deal with any logic.My trouble with the first method is that the burden is placed on the caller.My trouble with the second, at least in C, is that firstly I end up writing a whole load of boiler plate accessors and secondly more complex stuff like test-and-set or needing to hold a lock on the data whilst doing several operations becomes messy. E.g. for method 2 I needint GetData1(unsigned int index) {     int data;     ENTER_CR();     data = store[index].data1;     LEAVE_CR();     return data;}......int GetDataN(unsigned int index) {     int data;     ENTER_CR();     data = store[index].dataN;     LEAVE_CR();     return data;}And the same for all the setters. And then what if I want to set multiple items atomically? Gets hard!How to get some of the benefits of modularity and encapsulation but still have a flexible interface?
Modularity and encapsulation in C
c;encapsulation
When providing a thread-safe interface (with or with OOP) you need to make sure that your operations are at the level you want to be atomic. If setting or getting a single field is the level of atomic operation you want to support, then option 1 works. (On the other hand, getting and setting int's is atomic anyways)The reality probably is that a simple data object isn't the correct place in a design to provide thread safety, because as you noted you really do not know what the real operations the data is being used for are. You can still encapsulate thread safety, but it needs to be where you are doing something, not just storing something.