12

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

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

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

4

3 回答 3

3

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

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

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

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

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

于 2013-11-04T00:54:23.053 回答
3

C++11 §1.10/1 定义了以下术语:

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

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

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

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

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

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

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

于 2013-11-05T03:38:19.167 回答
0

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

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

于 2013-11-04T02:12:27.520 回答