Go to option B, making the critical section internal to the object. If a class user must use an external function to securely access the instance, it is inevitable that someone will not and the house will collapse.
You also need to think about what operational semantics you want to protect against multiple simultaneous reads and writes. If you put a lock in your receiver and setter, you can guarantee that your object is internally consistent, but users of your object can see multi-threaded artifacts. For example, if thread A writes 10 to a property of your object, and thread B writes 50 to this property of the same object, only one of them may be the last. If A happens first, then A will observe that they wrote 10 to the property, but when they read it again, they saw that B 50 breaks in there between A-read-after-write.
Note that you really don't need a lock to protect an entire whole field. Dedicated integer entries with a fixed pointer represent atomic operations for almost every hardware system today. You definitely need a lock to protect multicomponent data, such as structures or multi-step operations, such as changing two related fields at the same time.
If you can somehow redesign your project to make these objects local to a specific operation in the stream, do it. Creating local copies of the data can slightly increase the amount of memory, but it can greatly simplify your code for multithreading and work faster than leaving ground mutex mines throughout the application. Look for other simplifying assumptions: if you can configure your system so that the object remains unchanged as long as it is available for several threads, then the object does not need any security locks at all. Read-only data is useful for sharing streams. Very well.
dthorpe
source share