簡體   English   中英

boost::atomic_shared_ptr 絕對安全嗎?

[英]Is boost::atomic_shared_ptr absolutely safe?

眾所周知 std::shared_ptr 不是線程安全的。 所以很容易在web中找到很多崩潰的代碼示例,用簡單的程序來說明std::shared_ptr的缺點。 但是我找不到任何 boost::atomic_shared_ptr 這是否意味着我可以使用 boost::atomic_shared_ptr 而不必擔心它會使我的應用程序在多線程環境中崩潰? (當然 boost::atomic_shared_ptr 可以包含錯誤。所以我想知道 - “設計”是否安全。)

從 C++11 開始,您可以將 shared_pointer 與atomic_load / atomic_store一起使用,即使它在 c++20 中被取代:

https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic

我自己找不到很多示例,盡管我在這里使用了它: How to use boost::atomic_store with shared_ptr<T> and shared_ptr<const T>? ,這里是 https://github.com/sehe/msghub/blob/std-over-boost/src/msghub.cpp#L25

不管這一切,這些都不會使您的代碼安全,因為您仍將共享共享指針指向的對象,這使您的代碼像以前一樣容易發生數據競爭

您仍然需要為您的代碼添加適當的同步。

std::atomicstd::shared_ptr<> 是線程安全的,但僅用於讀取和寫入指針本身的值。 它的使用並沒有使 shared_ptr 的所有使用成為線程安全的。

考慮一下:

// using a single writer of data pointed to by foo for simplicity.

// contract: only set values from main thread (for example)
//           set values, then call apply_changes when all your parameters
//           are correct.
struct Foo
{
    void set_valueA(int x);
    //...  
    void set_valueZ(int x);

    void apply_changes();   
};   

// using global data for silplicity, tis could be a member of some class,
// or in any stable memory location in an application.       

// More than one thread may reallocate or reset this object, hence the std::atomic. 
std::atomic<std::shared_ptr<Foo>> global_ptr;   

void some_function()
{
    // Set or reset  global_ptr attributes

    if (!global_ptr)
        return;

    global_ptr->set_valueA(42);    // a bad_alloc exception could 
                                   // happen here

    // what happens if global_ptr is set or reset
    // by another thread in between these two statements?

    global_ptr->set_valueB(17);    // a bad_alloc exception may occur here.
    global_ptr->apply_changes();   // undefined behavior as per contract of Foo 
                                   // may happen here.
}

// for this reason, proper usage would be...

void some_function()
{
    // Set or reset  global_ptr attributes

    // since global_ptr is atomic, it is guaranteed that this line will not crash
    // and will always return a well-formed shared_ptr. If fact, that's the
    // one and only guarantee given by std::atomic<std::shared_ptr<>>.
    if (std::shared_ptr<Foo> local_copy = global_ptr)
    {
        // Note that local_copy is guaranteed to point to the same object until 
        // end of scope. 

        local_copy->set_valueA(42);
        local_copy->set_valueB(17);
        local_copy->apply_changes();

        // if global_ptr has changed, then memory will be released when 
        //  exiting scope. 
    }
}

因此,恕我直言,在使用原子共享指針時仍然必須采取一些基本的預防措施,無論是對指向數據的讀取還是寫入操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM