Lock shared resources in constructor and destructor

I believe that I am well versed in at least the basics of multithreading in C ++, but I could never get a clear answer to locking a mutex around shared resources in a constructor or destructor. I got the impression that you should be locked in both places, but recently, your colleagues have not agreed. Imagine several threads accessing the following class:

class TestClass { public: TestClass(const float input) : mMutex(), mValueOne(1), mValueTwo("Text") { //**Does the mutex need to be locked here? mValueTwo.Set(input); mValueOne = mValueTwo.Get(); } ~TestClass() { //Lock Here? } int GetValueOne() const { Lock(mMutex); return mValueOne; } void SetValueOne(const int value) { Lock(mMutex); mValueOne = value; } CustomType GetValueTwo() const { Lock(mMutex); return mValueOne; } void SetValueTwo(const CustomType type) { Lock(mMutex); mValueTwo = type; } private: Mutex mMutex; int mValueOne; CustomType mValueTwo; }; 

Of course, everything should be safe through the initialization list, but what about the statements inside the constructor? In the destructor, would it be useful to make a lock without binding and never unlock (in fact, just call pthread_mutex_destroy)?

+6
source share
2 answers

Multiple threads cannot create the same object, and no one is allowed to use this object until it is fully assembled. Thus, in smart code, a non-blocking design is safe.

Destruction is a little harder. But again, properly managing the life cycle of your object can ensure that the object will never be destroyed when it is likely that some threads may use it.

A generic index can help achieve this, for example.

  • build an object in a specific thread
  • pass shared pointers to every thread that needs access to the object (including the thread that built it, if necessary)
  • the object will be destroyed when all threads release a common pointer

But, obviously, there are other valid approaches. The key is to maintain the right boundaries between the three main stages of an object’s life: construction, use and destruction. Never allow overlapping between any of these steps.

+12
source

They should not be locked in the constructor, since the only way that any external can access this data at this point is to pass them from the constructor itself (or perform some undefined behavior, for example, calling a virtual method).

[Edit: deleted part about the destructor, because, as the comment rightly says, you have big problems if you try to access resources from an object that may be dead]

+1
source

Source: https://habr.com/ru/post/921318/


All Articles