C++ 使用原子引用计数时是否需要保护删除资源?

C++ 使用原子引用计数时是否需要保护删除资源?,c++,multithreading,reference-counting,C++,Multithreading,Reference Counting,在许多情况下,一个资源可以由多个线程共享。资源处理程序可以使用原子引用计数来处理这些资源 假设线程a中有一个资源处理程序,如std::string a。假设该std::string在内部使用原子引用计数机制。现在假设您创建了一个卷影副本,如std::string b=a,其中b用于线程b 我刚刚读了这个问题:这里有两个答案。他说下面的代码片段就足够了;注意:在没有任何互斥保护的情况下调用cleanup: if(InterlockedDecrement(&mRefCount)==0)

在许多情况下,一个资源可以由多个线程共享。资源处理程序可以使用原子引用计数来处理这些资源

假设线程a中有一个资源处理程序,如
std::string a
。假设该
std::string
在内部使用原子引用计数机制。现在假设您创建了一个卷影副本,如
std::string b=a
,其中b用于线程b

我刚刚读了这个问题:这里有两个答案。他说下面的代码片段就足够了;注意:在没有任何互斥保护的情况下调用
cleanup

if(InterlockedDecrement(&mRefCount)==0)
    cleanup();
但是,
cleanup
函数包装了一个互斥锁:

void decRef() {
    lock(_mutex);
    if(InterlockedDecrement(&mRefCount)==0) {
        cleanup(); //mainly delete some resource
    }
}
我的问题是,“第一个答案正确吗?”当实例
a
在线程a中被销毁时,这种情况如何:

if(InterlockedDecrement(&mRefCount)==0)
    // here, OS switch to another thread, and mRefCount is changed there
    cleanup();

…如果线程B中发生此类更改后,
mRefCount
可能会在线程B中同时更改(通过
B
),那么在线程a中调用
cleanup()
是否仍然安全?

我还没有尝试详细查看该答案,但我怀疑你关心的是这个问题,而不仅仅是那个问题

在典型的COW string1中,当引用计数降至0时,您不再需要使用互斥(或任何类似的)来保护清除

原因相当简单:至少在通常情况下,您只能通过复制字符串的某些现有引用来创建对该字符串的新引用。当引用计数降至零时,就不再存在任何现有引用,因此没有创建此类副本的源

如果您使用的不是COW字符串,则必须查看用法,以确定引用计数是否可能从起始值0递增。例如,您可以使用某种缓存来保存最近使用的值,该缓存使用引用计数,因此只要对象被引用,它就会留在缓存中。如果不存在对它的进一步引用,它将有资格从缓存中删除。下次需要向缓存中添加内容时,您将找到引用计数为0的最旧项,并将其替换为新项(如果没有引用计数为0的项,则根据缓存策略,您可以扩展缓存或拒绝缓存新项)

在这种情况下,可以找到引用计数为0的任何项,然后使用上下文开关添加对该项的引用,然后切换回(如果没有使用互斥锁保护清理),删除该项,即使该项现在具有非零引用计数


1.尽管在这里并不特别相关,但标准现在明确禁止使用
std::string
的写时复制实现。

再也没有人拥有对对象的有效引用了。因此,当然你不需要锁。在缓存的情况下,最好使用
std::weak_ptr
。嗨,杰瑞,这实际上是一个牛字符串问题,与缓存无关。谢谢你的帮助。