【问题标题】:Lifetime of std::thread argumentsstd::thread 参数的生命周期
【发布时间】:2013-11-15 07:16:20
【问题描述】:

当参数被传递到std::thread() 时,产生新线程的线程是否会等到所有参数都完全复制到新线程本地存储中?

简单示例:

void f()
{  
  int array[10];
  ........ //done something with array  
  std::thread th(someF, array); //assuming that someF accepts int[]  
  th.detach();  
}

我是否应该自动假设在f() 结束之前安全复制了所有数据? 我看到的一种情况是,假设f() 不等待并全力以赴,th 正试图复制正在被破坏的array

【问题讨论】:

  • 您不是将数组传递给该线程,而是将指针传递给第一个元素。

标签: c++ multithreading c++11 stl


【解决方案1】:

是的。如果复制失败,则会抛出构造线程。

§30.3.1.2 线程构造函数

模板显式线程(F&& f, Args&&... 参数);

要求: F 和 Args 中的每个 Ti 应满足 MoveConstructible 要求。调用(衰减_-复制( std::forward(f)), DECAY_COPY (std::forward(args))...) (20.8.2) 应该是一个有效的表达式。 4

效果:构造一个对象 类型的线程。新的执行线程执行 INVOKE (DECAY_- COPY (std::forward(f)), DECAY_COPY (std::forward(args))...) 在构造线程中评估对 DECAY_COPY 的调用。此调用的任何返回值都将被忽略。 [ 笔记: 这意味着调用 f 的副本时未抛出的任何异常都将在构造线程中抛出,而不是在新的 线程。 —尾注] 如果调用 INVOKE (DECAY_COPY ( std::forward(f)), DECAY_COPY (std::forward(args))...) 以未捕获的异常终止,应调用 std::terminate。

同步: 完成调用 构造函数与调用的开始同步 f.的副本。

【讨论】:

    【解决方案2】:

    是的,如果无法将参数复制到新线程可用的存储空间,它将引发异常。

    来自http://en.cppreference.com/w/cpp/thread/thread/thread

    在评估和复制/移动 参数是在当前线程中抛出的,而不是在新线程中。

    【讨论】:

    • 但是请注意,正确的术语是不是线程本地存储。它们被复制到线程可访问的存储中。 “线程本地”存储是一个不同的、有些争议的概念。
    • 我也注意到了这个特殊性,但是引用的页面有这个,逐字记录:“创建新的 std::thread 对象并将其与执行线程相关联。首先,构造函数复制/移动所有参数 args ...到线程本地存储”也许是错误的,或者还有更多?我将编辑答案以避免混淆。
    • 是的,提到“线程本地存储”是错误的。线程本地存储本质上是每个线程的静态存储(即,每个线程都有自己的线程本地数据副本,可以从线程中的任何函数按名称使用)。线程参数作为普通参数传递给被调用函数。
    • 仅供参考,该页面对“tread-local”的引用已更改为“thread-available”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-18
    • 2023-02-24
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    相关资源
    最近更新 更多