【问题标题】:thread local and context switch线程本地和上下文切换
【发布时间】:2013-01-24 11:38:46
【问题描述】:

我有一些使用线程本地存储的 C++ 代码,每个线程都有一个可以将数据推入的向量。

我使用 TLS 存储每个线程的索引 ID,这可用于查找将数据推送到哪个向量。然后它会执行大量代码,将数据推送到向量中。

我想知道的是,操作系统是否有可能在获取指向线程本地对象的指针后重新安排我的代码在不同的线程上执行。 (到目前为止,代码执行得很好,我还没有看到这种情况发生)。但如果可能的话,这似乎肯定会破坏我的程序,因为现在两个线程可以拥有相同的对象。

假设这是真的,即使对于使用任何复杂性 TLS 的任何代码,这似乎也是一个问题,TLS 是否仅适用于您不获取地址的简单对象?

谢谢!

【问题讨论】:

  • 你使用什么样的线程库?您是否创建自己的线程?使用偷工减料?
  • 我使用英特尔 TBB,没有显式线程,只是基于任务
  • AFAIK Intel TBB 不会在线程之间迁移任务,因此您是安全的。 (没有操作系统在你背后改变线程ID这样的事情)

标签: c++ context-switch thread-local-storage


【解决方案1】:

线程本地存储就是这样 - 每个线程的存储。每个线程都有自己的私有数据结构。该线程,无论它在哪个处理器上运行,都是同一个线程。操作系统不会在线程内安排工作,它会安排哪些线程运行。

线程本地存储是通过某种间接方式实现的,这种间接方式会随着线程本身的变化而改变。有几种方法可以做到这一点,例如,操作系统可能在进程中的虚拟内存开始的特定偏移处有一个特定的页面,并且当一个线程被调度时,页表被更新以匹配该线程。

在 x86 处理器中,FS 或 GS​​ 通常用于“每线程”数据,因此操作系统将切换 FS 寄存器[或在 64 位处理器的情况下,寄存器的基地址内容]。读取 TLS 时,编译器将使用 FS 或 GS​​ 段寄存器作为内存读/写操作的前缀,因此您始终获得“您的私有数据”,而不是其他一些线程。

当然,操作系统可能有错误,但这是很多东西都会依赖的东西,所以如果它坏了,它很快就会出现(除非它非常微妙,而且你必须站在正确的位置地点,月亮在正确的相位,穿着正确的颜色衣服,风向正确,日期可以被3和7整除,等等)。

【讨论】:

  • 嗯,好的,所以 TLS 特定于线程而不是硬件处理器,谢谢!
  • 嗯,它特定于线程运行的处理器,但如果线程移动,操作系统将随线程移动 TLS 设置。
【解决方案2】:

TLS 表示线程 local,根据您的描述,每个线程通过 TLS 访问一个共享向量向量(我不确定),您应该使用某种锁。有示例代码吗?

【讨论】:

    猜你喜欢
    • 2017-09-09
    • 2011-07-23
    • 1970-01-01
    • 2011-07-27
    • 2018-04-18
    • 2014-12-05
    • 2012-01-12
    • 2014-02-20
    相关资源
    最近更新 更多