首页 > 解决方案 > 自动引用计数系统中的赋值是线程安全的吗?

问题描述

Swift、Vala 和 C++ 等语言(通过 shared_ptr)通过引用计数来管理内存。据我所知,这些系统中对引用计数的更新是原子执行的,因此是线程安全的。

但是,每次重新分配引用/指针时,以前的引用对象需要引用计数递减,新引用的对象需要增加引用,最后必须重新分配引用本身。因此,如果同一个引用可以从多个线程访问(即通过一个全局变量)并且同时被多个线程重新分配,那么引用计数可能会出现乱码。

那么 C++ 共享指针、Vala 引用、Swift 引用是否采取措施避免此类问题?如果不是,在这三种语言中的每一种中都需要采取哪些步骤来确保这种访问安全?

任何见解都值得赞赏。谢谢!

标签: c++swiftmultithreadingvalareference-counting

解决方案


请参阅http://en.cppreference.com/w/cpp/memory/shared_ptr的最后一段

所有成员函数(包括复制构造函数和复制赋值)都可以由多个线程在 shared_ptr 的不同实例上调用而无需额外同步,即使这些实例是副本并共享同一对象的所有权。如果多个执行线程在没有同步的情况下访问同一个 shared_ptr 并且这些访问中的任何一个使用 shared_ptr 的非常量成员函数,则将发生数据竞争;原子函数的 shared_ptr 重载可用于防止数据竞争。

shared_ptr 变量不是线程安全的,如果一个或多个线程修改变量,则不应从多个线程访问该变量。管理同一个指针的多个变量是原子的,每个线程都可以自由修改自己的shared_ptr.

例如,这是不安全的:

#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <thread>

int main()
{
    std::shared_ptr< std::string > str( new std::string() );
    std::vector< std::thread > threads;
    for ( int i = 0; i < 10; i++ )
    {
        threads.emplace_back([&]
        {
            if ( str->empty() )
            {
                str.reset( new std::string( "thread string" ) );
            }
            else
            {
                str.reset();
            }
        });
    }
    for ( auto& thread : threads )
    {
        thread.join();
    }
}

但这是因为线程不会修改str变量,但会增加其引用计数:

#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <thread>

int main()
{
    std::shared_ptr< std::string > str( new std::string() );
    std::vector< std::thread > threads;
    for ( int i = 0; i < 10; i++ )
    {
        threads.emplace_back([&]
        {
            std::shared_ptr< std::string > str2 = str;
            if ( str2->empty() )
            {
                str2.reset( new std::string( "thread string" ) );
            }
            else
            {
                str2.reset();
            }
        });
    }
    for ( auto& thread : threads )
    {
        thread.join();
    }
}

C++20 添加了std::atomic_shared_ptr完全线程安全的。在此之前,您可以使用原子非成员函数。


推荐阅读