在C++线程中,我应该通过值还是引用传递shared_ptr?

微软的线程安全页面说,shared_ptr即使有多个副本共享同一个对象,也应该使用它。

那么这是否意味着以下两种情况都可以接受?我已经尝试了两者,它们似乎工作正常。

编辑:实际的业务目标是从长时间运行的线程到主线程获取字符串更新。我想我应该使用,shared_ptr因为string它不是线程安全的。不要诚实地关心所有权。

选项 1(传递参考):

auto status = std::make_shared<std::string>();
auto f = [&status]() {
    ...
  *status = "current status";
    ...
};

std::thread t{f};

while(true) {
  std::cout << *status << std::endl;
  std::this_thread::sleep_for(1000ms);
  if (*status == "completed") break;
}

t.join();

选项 2(制作副本):

auto status = std::make_shared<std::string>();
auto f = [](std::shared_ptr<std::string> s) {
    ...
  *s= "current status";
    ...
};

std::thread t{f, status};

while(true) {
  std::cout << *status << std::endl;
  std::this_thread::sleep_for(1000ms);
  if (*status == "completed") break;
}

t.join();

EDIT2:所以显然这两种方法对于我想要实现的目标都是错误的。我需要使用std::mutex( cppreference ) 而不是shared_ptr. 请参阅此答案的后半部分。

回答

通常,线程可能会在创建它们的范围内存活。在这种情况下,任何通过引用捕获的局部变量都可能在线程仍在运行时被销毁。如果是这种情况,则不应通过引用捕获。

此外,在一个线程中修改共享指针对象并在没有同步的情况下访问另一个线程会导致未定义的行为。如果这就是您所做的,那么您应该使用std::atomic_load/atomic_store函数访问指针,或者简单地将指针复制到每个线程中。请注意,您可以通过副本捕获:

auto f = [status]() {

此外,共享指针没有提供额外的线程安全来访问指向的对象,除了保持所有权处于活动状态并确保它被删除一次。如果指向的类型不是原子的,那么在一个线程中修改它并在没有同步的情况下访问另一个线程会导致未定义的行为。如果这就是你正在做的,你需要使用互斥锁或类似的东西。或者将指向的对象本身复制到每个线程中。

关于编辑后的问题:您的示例适用于最后一个案例。他们都有未定义的行为。你需要同步。

  • @AdrianMaire Standard says thus: `If a side effect on a memory location ([intro.memory]) is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent ([intro.multithread]), the behavior is undefined.` In short, *data race* is UB.

回答

shared_ptr通过引用接受是很奇怪的,因为您首先失去了使用的全部意义shared_ptr。您可以只使用原始指针。

在某些情况下,通过引用接受shared_ptr是合法的,但是如果您将它的引用提供给线程,那么一旦该实例shared_ptr被销毁并且线程仍然使用shared_ptr.

的主要目的shared_ptr是管理对象的生命周期。如果你将它的引用传递给一个线程,那么你就抛弃了shared_ptr.

  • Why passing a shared_ptr as reference (in general, not speaking of threads) lose the whole point of using it? Obviously, passing a reference and deleting it object will cause UB, but isn't that the case for all references?

以上是在C++线程中,我应该通过值还是引用传递shared_ptr?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>