问题标签 [thread-local-storage]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
21298 浏览

linux - 什么是汇编中的 %gs

在 gcc 中编译后,该函数转换为以下汇编代码:

我不明白两行:

什么是%gs,这两行到底是做什么的?

这是编译命令:

0 投票
3 回答
8764 浏览

c++ - CWnd::GetSafeHwnd() 和 CWnd::m_hWnd 是线程安全的吗?

我在一个高度多线程的应用程序上面临许多崩溃。

阅读这些 MSDN页面技术说明这篇关于 TLS的文章,我了解到CWnd对象在 Thread Local Storgae(TLS,这是一个线程相关的内存访问)中映射到 HWND。

我打算解耦所有看起来像 CWnd 线程远程访问的东西,并将其转换为HWND引用,然后::PostMessage用作通信端口。

但是我的一位同事确实坚持我只是保留CWnd*在外国线程中,采用::PostMessage策略可以,但是在外国线程中使用CWnd::GetSafeHwnd()orpMyCWnd->m_hWnd以便恢复本地HWND

我一直在争辩说,我在任何地方都没有看到它GetSafeHwnd()是线程安全的,并且CWnd对象在 TLS 中,它在另一个线程中的值是不同的。

我错了 ?MSDN 显然使用了Unexpected results一词。

CWnd::GetSafehwnd()关于从创建者线程调用或pMyCWnd->m_hWnd在外部线程中,您的观点是什么?

您是否有任何 MSDN 文档说明这是否安全。

0 投票
1 回答
3636 浏览

c++ - 如何在动态加载的 DLL 中正确实现(C++)线程本地存储?

在这种情况下,我的动态加载的 DLL 由 Windows 资源管理器加载,以便将新的属性表(新选项卡)添加到文件/文件夹属性页面。

一个简单的例子是StrmExt.dll(下载源)。在此示例中(由 Microsoft 提供的源代码),DLL 不使用线程本地存储 (TLS),因此在同时加载多个属性页时会导致严重问题。

在查看源代码后,DLL 需要一个基于线程的变量(文件的文件路径)......

将这一行代码更改为:

... 使 DLL 能够支持多个线程,从而支持属性表的多个实例。但是,我知道只有 Windows Vista 和更新版本才支持此更改(在 Windows 7 上的测试非常积极)。例如,XP 不支持动态加载的库...而且已知会导致应用程序崩溃。(见最后一段)。

为了在 XP 上运行,我不能使用这个声明。我怀疑我需要从以下方面增强他们的 DLL 入口点:

......像这样......如前所述here

无论我创建 1 个还是 2 个线程,这在第一次加载 DLL 期间都可以正常工作。释放 DLL 后,资源管理器在下次加载库时崩溃。

我有什么误解?我注意到原始开发人员在 DLL 进程附加通知时故意禁用线程通知。为什么?

0 投票
3 回答
9658 浏览

java - 在实例变量中使用 ThreadLocal

如果JavaThreadLocal变量用作实例变量(例如,在生成线程局部对象的方法中),它们是否会产生线程局部值,或者它们必须始终是静态的吗?

作为一个例子,假设一个典型的场景,其中几个,昂贵的初始化一个非线程安全的类的对象,需要在单个静态初始化块中实例化,存储在单个类的静态变量中(例如,在Map数据结构),从那时起用于许多不同线程的密集处理。

为了实现线程安全,显然必须传递每个静态对象的不同副本。例如,DateFormat需要跨不同线程安全使用的 Java 对象。

在网上可以找到的许多示例中,该方法似乎是分别声明每个ThreadLocal变量,在方法中实例化新对象,initialValue()然后使用该get()方法检索线程本地实例。

如果要创建数十或数百个这样的对象,每个对象都有自己的初始化参数,那么这种方法不是很有效。例如,许多SimpleDateFormat对象各自具有不同的日期模式。

如果对象的实例化可以在每次迭代中产生不同值的循环中完成,则在通过正确初始化相应对象创建每个值之后,将需要用于产生线程局部实例的通用方法。

基于上述情况,以下通用静态方法将不起作用,因为每次调用 initialValue() 时都会产生相同的引用:

相反,需要一种在 initialValue() 中创建新对象的机制。因此,唯一的通用方法可能是使用反射,其模式类似于

然后,当然,还有一个特定于类型的选项,可以只使用ThreadLocal循环中的模式来声明每个变量。

例如,在 的情况下DateFormat,在单个静态初始化块中,可以执行

从那时起,formats映射将被不同的类、跨不同的线程每次读取,以便调用存储在映射中的一个或多个对象的format()or方法。parse()DateFormat

上述任何方法是否对所描述的情况有意义,或者ThreadLocal声明应该是静态的?

0 投票
3 回答
3251 浏览

windows - 内核模式下的线程本地存储?

Windows 中的内核模式驱动程序是否有等效的线程本地存储 (TLS)(准确地说是 Win32)?

我试图达到的目标:

最终,在我的驱动程序的调度例程中,它可能会调用许多其他函数(可能有很深的调用堆栈)。我想提供一些特定于正在处理的请求的上下文信息。也就是说,我有一些结构,指向它的指针应该在所有被调用的函数中都是可见的,而不是显式地将它作为参数传递给每个函数。

使用静态/全局不是一个完美的选择(多线程、同步对象等)。

如果那是用户模式代码 - 在这种情况下显然会使用 TLS。但是 AFAIK 没有像TlsGetValue/这样的内核模式函数TlsSetValue。这是有道理的——要使这些功能正常工作,必须首先分配一个进程范围的 TLS 索引。OTOH 驱动程序代码可以在任意线程上调用,不限于特定进程。

但是,我实际上并不需要持久的特定于线程的存储。我只需要一个特定于线程的存储来进行顶级函数调用。

我想我知道如何“实施” TLS,尽管是以一种骇人听闻的方式。我不会分配 TLS 索引,而是始终使用预定义的索引(例如 index=0)。在顶级函数中,我将保存存储的 TLS 值,并用所需的值覆盖它。完成后,保存的值将被恢复。

幸运的是,我知道 TLS 在 Win32 中是如何实现的。每个线程都有一个TIB结构(线程信息块)。在每个线程中都可以使用FS:[18h]选择器访问它。包含(除其他外)TLS 使用的TIB数组。其余的非常简单。

但是我更喜欢使用官方 API 来实现类似的东西。

  • 是否有官方的内核模式 API 来实现我所需要的?
  • 是否有理由避免我打算做的事情?我知道重入可能存在问题(即某些代码调用我,我覆盖 TLS 值,然后最终调用可能依赖于 TLS 的原始代码)。但这在我的具体情况下是不可能的?
  • 有没有更脏的方法来解决这个问题?

提前致谢。

PS One 理论上可以使用 SEH(它还存储了每个线程的信息)。也就是说,用 包装顶层代码__try/__except,然后在需要上下文信息的地方 - 用一些参数引发可继续异常,在__except块中用上下文信息填充参数,然后恢复执行。这是一个 100% 有效的程序流程,没有使用未记录的功能。但尽管如此,这对我来说似乎是一个丑陋的 hack,更不用说性能上的复杂性了。

0 投票
1 回答
1729 浏览

tbb - 关于 TBB 线程本地存储

我很难理解 TBB 的特定可枚举线程。我写了这个小代码来测试 TLS

但输出很尴尬。有时是:

有时是:

为什么会发生这种变化?此外,在 TBB 论坛中,我读到有时 TLS 不包含所有预期值,但其原因显然是关于父任务和子任务的关系。不过也不是太明白。

有什么帮助吗?

谢谢你。

0 投票
3 回答
1429 浏览

c - 如何从 ml64.exe(MSVC 64 位 X64 汇编程序)访问线程本地存储?

以下 C 函数尝试使用线程本地存储变量以线程安全的方式防止多核代码中的递归。但是,由于有些复杂的原因,我需要在 X64 汇编程序(Intel X86 / AMD 64 位)中编写此函数,并使用 VC2010 中的 ml64.exe 进行汇编。如果我使用全局变量,我知道如何执行此操作,但我不确定如何使用具有 __declspec(thread) 的 TLS 变量正确执行此操作。

注意:这是 VC2010 为该功能踢出的。但是,MASM (ml64.exe) 不支持代码的一部分gs:88OFFSET FLAT:部分。

0 投票
1 回答
968 浏览

.net - 当使用不同的线程进行相同的操作时,WCF 不会传播 Trace.CorrelationManager 的属性

当 WCF 对同一操作使用不同的线程时,如何让 WCF 传播 Trace.CorrelationManager 的属性?

我知道 WCF 不保证线程亲和性。所以基本上一个线程可以启动一个请求,另一个线程可以完成它。当我重现此行为时,我看到第一个线程具有正确设置的两个属性 Trace.Correlation.ActivityId 和 Trace.Correlation.LogicalOperationStack。WCF 使用不同的线程完成了操作,但未传播属性。

为了解决这个问题,我可能不得不放弃使用 CorrelationManager 并且可能必须将 ActivityId 存储在 OperationContext 中,我知道它会传播到新线程(如果我在这里错了,请纠正我)。我不想这样做,因为它当然需要更多的工作,而且不如使用单个属性那么优雅。

关于如何解决这个问题的任何其他想法?我可以告诉 WCF 以某种方式为我传播这个吗?

谢谢,穆罕默德

0 投票
1 回答
2314 浏览

wcf - 将 OperationContext.Current 存储在 WCF 服务实例的实例变量中

我想知道在 WCF 服务主机实例的实例变量中存储和引用 OperationContext.Current 对象是否明智。服务主机设置为 InstanceContextMode.PerCall,因此每个新请求都有自己的实例。

我问这个的原因是因为 WCF 不保证线程亲和性。有时,WCF 可以在一个线程上启动请求并在另一个线程上结束请求。

OperationContext.Current 对象存储在线程本地存储中。当新线程用于同一操作时,WCF“传播”到新线程。

在这种情况下,当 WCF 开始使用不同的线程时,访问存储在我的服务实例的实例变量中的 OperationContext 对象是否仍然安全?

0 投票
1 回答
779 浏览

gwt - GWT 中的本地请求上下文

在 Java 中,有 ThreadLocal,它可用于将一些数据从一个对象传送到另一个对象,而无需显式传递作为方法参数。

我需要拦截 GWT 请求并从中提取自定义 HTTP 标头,然后我需要以某种方式存储标头值以便以后处理。

问题是提取标头的位置属于 RequestBuilder,并且无法(?)将变量从 RequestBuilder 传递到实际处理来自服务器的请求/响应的自定义代码。并且不可能将某些变量从客户端代码传递给该请求构建器。

ThreadLocal 可能是解决方案,但它在 GWT 中不可用。有什么我可以使用的吗?