Is unique_ptr thread safe?
No, it isn't thread-safe.
Both threads can potentially move
the work pointer with no explicit synchronization, so it's possible for both threads to get the same value, or both to get some invalid pointer ... it's undefined behaviour.
If you want to do something like this correctly, you probably need to use something like std::atomic_exchange
so both threads can read/modify the shared work pointer with the right semantics.
Is creating unique_ptr thread safe
Is creating unique_ptr thread safe
The creation of std::unique_ptr
from the pointer is thread safe. Furthermore, accessing a unique index of an array is thread safe.
Although constructors are often thread safe, we cannot know whether the default constructor of SomeClass
is safe without knowing its definition.
Furthermore, accessing the created pointer from other threads later will require synchronisation.
Note that writing adjacent indices of an array of pointers from separate threads is a case where false sharing may impede the performance.
unique_ptr with multithreading
If I check
unique_ptr != nullptr
, is it thread safe
No, it is not thread safe. If you have more than one thread and at least of one of them writes to the shared data then you need synchronization. If you do not then you have a data race and it is undefined behavior.
m_bigClass.reset(new BigClassCreatedOnce()); // created only once
and
if (!m_bigClass)
Can both happen at the same time, so it is a data race.
I would also like to point out that
if (m_bigClass->var.load())
Is also not thread safe. var.load()
is, but the access of m_bigClass
is not so you could also have a data race there.
std::shared_ptr thread safety explained
As others have pointed out, you've got it figured out correctly regarding your original 3 questions.
But the ending part of your edit
Calling reset() in thread IV will delete previous instance of A class created in first thread and replace it with new instance? Moreover after calling reset() in IV thread other threads will see only newly created object?
is incorrect. Only d
will point to the new A(10)
, and a
, b
, and c
will continue to point to the original A(1)
. This can be seen clearly in the following short example.
#include <memory>
#include <iostream>
using namespace std;
struct A
{
int a;
A(int a) : a(a) {}
};
int main(int argc, char **argv)
{
shared_ptr<A> a(new A(1));
shared_ptr<A> b(a), c(a), d(a);
cout << "a: " << a->a << "\tb: " << b->a
<< "\tc: " << c->a << "\td: " << d->a << endl;
d.reset(new A(10));
cout << "a: " << a->a << "\tb: " << b->a
<< "\tc: " << c->a << "\td: " << d->a << endl;
return 0;
}
(Clearly, I didn't bother with any threading: that doesn't factor into the shared_ptr::reset()
behavior.)
The output of this code is
a: 1 b: 1 c: 1 d: 1
a: 1 b: 1 c: 1 d: 10
Thread safety with std::shared_ptr
std::shared_ptr
instances are not thread safe. Multiple instances all pointing to the same object can be modified from multiple threads but a single instance is not thread safe. See https://en.cppreference.com/w/cpp/memory/shared_ptr:
All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of shared_ptr without additional synchronization even if these instances are copies and share ownership of the same object. If multiple threads of execution access the same shared_ptr without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur; the shared_ptr overloads of atomic functions can be used to prevent the data race.
You therefore either need to lock your mutex in your get_obj
method or use std::atomic_load
and std::atomic_store
in your start
and stop
methods
Thread safe unique_ptr move
No, this is not possible.
The value T
which you pass to std::atomic
needs to be trivially copyable, which std::unique_ptr
is not. Operations like std::atomic::load
or std::atomic::store
take T objects by value.
Packing something in a std::atomic
also doesn't make operations from the value atomic.
When using std::unique_ptr
in an atomic context, you have to think about the fact that you might have problems when it comes to managing resources. You never know how many threads still refer to your data, this problem can be solved with a std::shared_ptr
which uses atomic reference counting. (You need to check whether it's really atomic by using the std::atomic_is_lock_free
function. )
One thing I was also stumbling upon when looking in your code is the intent of the borrowSyncToken
function. It's called borrow but you pass ownership of the token to the caller by moving out the std::unique_ptr
, how is the ownership passed back and what do other threads get when the DataManager currently doesn't own the token?
Related Topics
Multithreading on Dual Core MAChine
How to Resize an Image to a Specific Size in Opencv
Template Assignment Operator Overloading Mystery
How to Perform Rgb->Yuv Conversion in C/C++
Openmp and Reduction on Std::Vector
Neatest Way to Loop Over a Range of Integers
How to Know When a New Usb Storage Device Is Connected in Qt
Factor a Large Number Efficiently with Gmp
Why Uninitialized Global Variable Is Weak Symbol
Dealing with Library Dependencies on Linux
Absence of Typeof Operator in C++03
How to Wrap Functions with the '--Wrap' Option Correctly
C++ 'Strcpy' Gives a Warning (C4996)
Communication Between Native-App and Chrome-Extension
What Is a Possible Workaround for Object Slicing in C++