c++ - GCC 原子 shared_ptr 实现

标签 c++ multithreading gcc shared-ptr stdatomic

根据 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57250 ,GCC 4.9 支持原子 shared_ptr操作。

使用 GCC 4.9.2,我能够编译一个使用 atomic shared_ptr 的程序. -mcx16标志是必需的,因为 x86_64 上的 GCC 实现显然需要 cmpxchg16b ,这是有道理的,因为我会假设对 shared_ptr 的原子操作将需要同时自动更新指针本身和引用计数。

但是,当我尝试实际使用原子 shared_ptr库,它的行为与我预期的不一样。所以,要么我没有正确使用它,要么 GCC 实现有缺陷。大多数时候,我有 99% 的把握认为我只是做错了,但由于这是一个相对较新的功能,而且行为看起来很奇怪,所以我只有大约 50% 的把握认为这是我的错案例。

这是一个创建原子 shared_ptr 的简单程序,然后在 shared_ptr 上执行一系列并发读取和写入:

void test()
{
        std::atomic<std::shared_ptr<int>> p(std::shared_ptr<int>(new int(10)));

        std::cout << "Use count : " << p.load().use_count() << std::endl;
        std::cout << "Initial value of p : " << *(p.load()) << std::endl;

        std::vector<std::thread> threads;
        const std::size_t num_threads = 8;

        for (std::size_t i = 0; i != num_threads; ++i)
        {
                threads.emplace_back([&p, i](){

                        std::shared_ptr<int> x = p.load();
                        while (!p.compare_exchange_weak(
                                x,
                                std::shared_ptr<int>(new int(i + 5))
                        )) ;
                });
        }

        for (auto& t : threads) t.join();

        std::cout << "Use count : " << p.load().use_count() << std::endl;
        std::cout << "Final value of p : " << *(p.load()) << std::endl;
}

当我编译并运行时,输出是:

~$ g++ test2.cpp -o test2 -std=c++11 -lpthread -mcx16
~$ ./test2
Use count : 1
Initial value of p : 0
Use count : 0
Final value of p : 0

但是这个输出对我来说毫无意义。首先,在初始化原子 shared_ptr 之后值为 10 ,当我加载它并读取初始值时(在生成任何线程之前),我得到一个 0 .其次,所有线程加入后,值还是0 ,即使没有线程可能将其设置为 0 .最奇怪的是,线程加入后,use_count() shared_ptr 的是 0 !然而原子shared_ptr对象仍在范围内,因此使用计数应为 1 .

我很确定这里的 GCC 实现是有缺陷的,但是根据我上面发布的链接,GCC 4.9 有一个完整的原子 shared_ptr实现,以及...

~$ gcc --version
~$ gcc (Debian 4.9.2-10) 4.9.2

那么……这里究竟发生了什么?我想得到某种确认,即此处的 GCC 4.9.2 实现存在缺陷或不完整,或者我完全错误/对如何使用原子 shared_ptr 感到困惑。 .

最佳答案

“原子 shared_ptr 操作”指的是 的免费 std::atomic_(store|load|exchange|compare_exchange_strong|compare_exchange_weak)(_explicit)? 函数模板>shared_ptr,已记录 here . GCC 直到 5 才拥有它们。(有趣的事实:它的实现实际上在引擎盖下使用了一个包含 16 个互斥锁的全局数组。)

std::shared_ptr 上实例化 std::atomic 会导致未定义的行为,因为 std::atomic 需要一个简单的可复制类型。

并发 TS 有 std::experimental::atomic_shared_ptr

关于c++ - GCC 原子 shared_ptr 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37198325/

相关文章:

c++ - 将 CMAKE 变量添加到 KDevelop 中的项目

c++ - 信号和插槽在 qt 中不起作用

C++/SDL 线程 - 事件分解

java - 返回ThreadPool时清除ThreadLocal值

c++ - 来自 std 的 unordered_set

c++ - QT:使用 move 语义将信号连接到插槽

c++ - 使用 CNG 存储功能将持久 key 导入 Windows key 存储

java - 混合实例和静态同步方法,得到意外的测试输出

c++ - 我的 C++ 代码在宏+模板编译时失败,为什么会出现这个错误?

c++ - 在enable_if_t中调用constexpr函数