gpt4 book ai didi

multithreading - 访问由 shared_ptr 持有的类的原子成员

转载 作者:行者123 更新时间:2023-12-03 22:41:11 25 4
gpt4 key购买 nike

我正在尝试创建一个小类,以促进两个线程之间的通信。

当这些线程排队到线程池时,它们很可能会超过创建上述类的上下文。

到目前为止我尝试了什么(on coliru as well):

class A    
{
public:
A(int maxVal) : maxValue(maxVal) {}
bool IsOverMax() const { return cur >= maxValue; }
void Increase() { cur++; }

private:
const int maxValue;
atomic_int cur{ 0 };
};

可能的用法:

void checking(const shared_ptr<A> counter)
{
while(!counter->IsOverMax())
{
cout<<"Working\n"; // do work
std::this_thread::sleep_for(10ms);
}
}

void counting(shared_ptr<A> counter)
{
while (!counter->IsOverMax())
{
cout<<"Counting\n";
counter->Increase(); // does this fall under `...uses a non-const member function of shared_ptr then a data race will occur`? http://en.cppreference.com/w/cpp/memory/shared_ptr/atomic
std::this_thread::sleep_for(9ms);
}
}

int main()
{

unique_ptr<thread> t1Ptr;
unique_ptr<thread> t2Ptr;

{
auto aPtr = make_shared<A>(100); // This might be out of scope before t1 and t2 end
t1Ptr.reset(new thread(checking, aPtr)); // To simbolize that t1,t2 will outlive the scope in which aPtr was originaly created
t2Ptr.reset(new thread(counting, aPtr));
}

t2Ptr->join();
t1Ptr->join();
//cout<< aPtr->IsOverMax();
}

我担心的原因是 documentation说:

If multiple threads of execution access the same std::shared_ptr object without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur unless all such access is performed through these functions, which are overloads of the corresponding atomic access functions (std::atomic_load, std::atomic_store, etc.)

  • 所以 Increase 是一个非 const 函数,对于这个上下文,aPtr 的副本是否相同的 std::shared_ptr
  • 这段代码是线程安全的吗?
  • 这对于非原子对象是否可行(比如使用 std::mutex 来锁定对常规 int 的读写)?
  • 无论如何,为什么?

最佳答案

So Increase is a non const function, are the copies of aPtr are the same std::shared_ptr for this context or not ?

std::thread 创建时,aPtr 按值传递。因此,保证:

  • 您不会引入数据竞争,因为每个线程都有自己的 shared_ptr 实例(尽管它们管理同一个对象 A)。
    您所指的文档描述了多个线程在同一个 shared_ptr 实例上运行的场景。在那种情况下,只能调用 const 成员函数(见下文),或者需要同步。
  • shared_ptr 引用计数在 aPtr 超出 main
  • 范围之前递增

是的,这是使用 shared_ptr 的正确方法。

Is this code thread-safe?

您的代码没有引入数据竞争,既没有访问 shared_ptr 实例,也没有访问托管对象 A。这意味着多个线程不会对同一内存位置执行冲突的、非原子的读写操作。

但是,请记住,在 checking() 中,对 IsOverMax() 的调用与随后的实际工作是分开的(Increase() 可以在 IsOverMax() 之后但在“工作”之前由第二个线程调用)。因此,您可以在 cur 超过其最大值时“工作”。这是否是一个问题取决于您的规范,但它被称为竞争条件,不一定是编程错误(与导致未定义行为的数据竞争不同)。

Would this be OK for a non atomic object (say using an std::mutex to lock around reads and writes to a regular int)?

如果您使用 std::mutex 保护它,

cur 可以是常规的 int(非原子)。必须为写 读访问锁定互斥锁,以防止数据竞争。

关于在多个线程共享的对象上调用const 成员函数的评论。
单独使用 const 并不能保证不会引入数据竞争。
在这种情况下,保证适用于 shared_ptr const 成员函数,因为文档是这么说的。
我在 C++ 标准中找不到该保证是否适用于标准库

中的所有 const 成员函数

关于multithreading - 访问由 shared_ptr 持有的类的原子成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48011033/

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