gpt4 book ai didi

c++ - 删除原子/防护数据中的数据

转载 作者:行者123 更新时间:2023-11-28 02:30:07 25 4
gpt4 key购买 nike

假设我们在 C++11 程序中使用标准的消费者/生产者模式:(来自:http://en.cppreference.com/w/cpp/atomic/memory_order)

#include <thread>
#include <atomic>
#include <cassert>
#include <string>

std::atomic<std::string*> ptr;
int data;

void producer()
{
std::string* p = new std::string("Hello");
ptr.store(p, std::memory_order_release);
}

void consumer()
{
std::string* p2;
while (!(p2 = ptr.load(std::memory_order_consume)))
;
assert(*p2 == "Hello"); // never fires: *p2 carries dependency from ptr

// yea well, it actually uses p2 for quite a while probably....
}

int main()
{
std::thread t1(producer);
std::thread t2(consumer);
t1.join(); t2.join();
}

现在,我想稍微改变生产者代码的行为。我不想简单地设置一个字符串,而是希望它覆盖一个字符串。例如:

void producer()
{
std::string* p = new std::string("Hello");
ptr.store(p, std::memory_order_release);

// do some stuff

std::string* p2 = new std::string("Sorry, should have been Hello World");
ptr.store(p2, std::memory_order_release);

// **
}

这里的生产者负责字符串的生成,这意味着在我的简单世界中它也应该负责这些字符串的销毁。

因此,在标有“**”的行中,我们应该销毁字符串“p”,这就是本题的内容。

您可能考虑的解决方案是添加(在标记行):

delete p;

但是,这会破坏程序,因为消费者可能会在我们删除它之后使用该字符串——毕竟,消费者使用的是指针。此外,这意味着生产者等待消费者,这不是必需的——我们只是希望清理旧内存。使用引用计数智能指针似乎是不可能的,因为原子只支持那么多类型。

解决此问题的最佳(最有效)方法是什么?

最佳答案

你可以做一个 atomic exchange ,这将返回原子变量的先前值。

变量 ptr 然后有两种状态:它可以没有可用数据,在这种情况下它等于 nullptr,或者有数据可供使用。

消费数据,任何消费者都可以用nullptr交换ptr

  • 如果没有数据,仍然没有任何数据,消费者将不得不稍后重试(这有效地构建了一个自旋锁)。

  • 如果有数据,消费者现在获得所有权并负责在不再需要时将其删除。

为了产生数据,生产者用指向产生数据的指针交换ptr

  • 如果没有数据,前一个指针将等于nullptr,数据成功生成。
  • 如果有数据,生产者实际上收回了之前生产的数据的所有权。然后它可以删除该对象,或者 - 更有效地 - 简单地将其重新用于下一次生产。

关于c++ - 删除原子/防护数据中的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29254785/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com