【问题标题】:What does C++11 consider to be a "thread"?C++11 认为什么是“线程”?
【发布时间】:2013-11-14 14:45:21
【问题描述】:

C++11 有一些线程的概念。例如,它定义了一个新的存储说明符 thread_local,并指定对于具有此存储说明符的变量,“每个线程都有一个不同的对象或引用”[basic.stc.thread]。

为此目的,什么被视为“线程”?是否只有使用标准线程库创建的线程(即由std::thread 对象表示的线程)?通过其他方式创建的线程(例如,直接在 Linux 上使用 pthreads)呢?如果我使用提供用户空间线程的库怎么办?每个线程都有自己的thread_local 对象副本(我真的不知道如何实现)?

如果答案是“它是由实现定义的,出于thread_local 之类的目的,它被认为是一个线程”,有人可以举一个例子来说明一个众所周知的实现是如何定义的吗?

【问题讨论】:

  • @texasbruce Java now 有那些关键字?他们在 17 年前就在那里。

标签: c++ multithreading c++11 language-lawyer thread-local-storage


【解决方案1】:

由于这些引号或main 标准状态在其自己的执行线程中运行,因此只有来自线程的组件支持库计数。

1 以下子条款描述了用于创建和管理线程 (1.10)、执行互斥以及在线程之间通信条件和值的组件,如表 148 所示。

到 1.10 的链接意味着正在谈论的线程就是这些。

1 执行线程(也称为线程)是程序中的单个控制流,包括初始...

因此,在我看来,threads 仅指 stdlib 线程(意味着 std::thread 和线程支持库在内部执行的任何操作)。当然thread_local 在许多情况下最终可能会使用本机线程(特别是当您考虑在特定系统上实现线程时通常不会有多个选择),但据我所知,标准没有保证。

【讨论】:

  • 虽然这是真的,并且实现在技术上可以摆脱支持thread_local 仅使用std::thread 这将是一个质量差的实现。到目前为止,现有实现确保thread_local 与系统线程一起工作,并让std::thread 通过系统线程库支持获得对thread_local 的支持。
  • @bames53 不确定这如何适用于我的答案,我只是说 C++ 中的“线程”是在内部实现的,std::thread 显然是其中之一,但其他内部的东西可能会产生一个“线程”。即使在内部实现使用我们说的 pthreads,并且它们最终作为“线程”工作,该标准也知道这个 IMO 的保证。
  • 是的,我同意你的观点,标准不保证std::thread 以外的任何内容。我只是在实践中补充一点,我知道thread_local 将与系统线程一起工作,而不仅仅是std::thread
  • @bames53 是的,很可能,正如我在编辑中所说,在实施这类东西时,您并没有太多选择
  • 还可以理解,main 在自己的线程上运行,具有自己的thread_local 变量,即使没有std::thread 对象。
【解决方案2】:

C++11 §1.10/1 定义了这些术语:

执行线程(也称为线程)是程序中的单一控制流,包括特定顶级函数的初始调用,并递归地包括线程随后执行的每个函数调用。 [ 注意: 当一个线程创建另一个线程时,对新线程顶层函数的初始调用由新线程执行,而不是由创建线程执行。 — 尾注 ]

斜体字表示这是确定的。您可能会争辩说这个定义在数学上是有缺陷的,因为每个函数调用都定义了一个新线程,但这显然是错误的。它们表示最大单一控制流,否则非规范注释将取消规范“递归包含”文本的效果。

从核心语言的角度来看,std::thread 导致这样的事情存在只是偶然的。

如果我使用提供用户空间线程的库会怎样?每个线程都有自己的 thread_local 对象副本(我真的不知道如何实现)?

没有内核调用就无法编写这样的库。很可能您进程中的所有线程都已经表示为高级抽象,例如 pthreads,只是为了满足内核。 C++ 标准库很可能是针对本机线程库编写的,以“正常工作”而无需额外的胶水。

例如,thread_local 对象在第一次访问时初始化,而不是在每个新线程启动时进行初始化,因此编译器只需插入基于 pthread_self 的查询即可访问并可能进行初始化。初始化将使用pthread_cleanup 设施注册一个析构函数。

这里的实现定义是预先存在的本机库是否与 C++ 兼容。假设他们提供了这一点,并且这是客户倾向于想要的东西,那么在它之上构建的所有其他线程库将自动兼容,除非出现其他冲突。

【讨论】:

  • 因此,要真正回答 OP 的问题,您相信任何在程序中创建新控制流的东西都可以按照标准使用 thread_local 之类的东西
【解决方案3】:

该标准没有描述其他库和系统调用产生的线程的行为方式。就标准而言,它们的行为未定义。在 C++ 中没有其他方法可以创建多个线程:此类库或系统调用执行 C++ 标准未标准化的操作。

现在,每个此类库和系统调用都将按照其自身规范定义的方式运行。很多时候,C++ std::thread 甚至会构建在此类库或系统调用之上。没有具体说明交互的工作原理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多