Consider the following class
with a shared_ptr
data object. The purpose is to obtain cheaply copyable objects with a data cache shared among the copies.
#include <memory> // std::shared_ptr
#include <mutex> // std::mutex, std::lock_guard
class DataClass {
std::shared_ptr<DataType> data;
std::shared_ptr<std::mutex> data_lock;
public:
DataClass() : data(std::make_shared<DataType>()), data_lock(std::make_shared<std::mutex>()) {}
DataType get_data() const {
std::lock_guard<std::mutex> lock_guard(*data_lock);
if (/* data not cached */) {
/* calculate and store data */
}
return *data;
}
};
Are calls to get_data()
thread-safe? If not, how can that be achieved?
I do have code that seems to end up in a deadlock (far too large/complicated to post), which relies on the above to work fine in parallel calculations.
Are calls to
get_data()
thread-safe?
As long as data_lock
is not modified after the initialization in the DataClass
constructor, it is thread-safe. shared_ptr
itself is not thread-safe beyond reference counting, meaning that if the pointer itself is modified, it must be protected with a mutex. If it remains constant (which you can ensure by marking data_lock
with const
) then multiple threads can read the pointer concurrently, including copying the pointer and incrementing/decrementing the reference counter.
If not, how can that be achieved?
If you do have an instance where data_lock
can be modified, you must protect it with a mutex lock or otherwise guarantee that the modification cannot happen while other threads are accessing the pointer. In this particular case this would probably mean to get rid of data_lock
pointer and replace it with a mutex.
You should also take care to not allow the pointed object to be accessed after data_lock
is modified. Remember that dereferencing shared_ptr
returns a raw reference without incrementing the reference counter. If that shared_ptr
is modified, the object it previously pointed to can be destroyed and the raw references become dangling. This can happen in a subtle way, eg a reference to the mutex may be saved in a lock_guard
, so after you modify data_lock
under the lock the lock_guard
destructor will attempt to unlock an already destroyed mutex.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.