Is Unique_Ptr Thread Safe

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_ptris 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



Leave a reply



Submit