S.J*_*.J. 6 c multithreading thread-local-storage
假设有一些使用全局变量的不可重入函数:
int i;
void foo(void){
/* modify i */
}
Run Code Online (Sandbox Code Playgroud)
然后,我想在多线程代码中使用此函数,因此我可以这样更改代码:
void foo(int i){
/* modify i */
}
Run Code Online (Sandbox Code Playgroud)
或者,通过使用gcc __thread说明符,更简单:
__thread int i;
void foo(void){
/* modify i */
}
Run Code Online (Sandbox Code Playgroud)
最后的优点是我不需要更改另一个调用foo()的代码.
我的问题是,线程本地存储的开销是多少?TLS有一些不明显的问题吗?
如果我将通过单独的指针修改TLS`ed变量,是否有一些开销,如下所示:
__thread int i;
void foo(void){
int *p = &i;
/* modify i using p pointer */
}
Run Code Online (Sandbox Code Playgroud)
谢谢.
Jon*_*Jon 10
然后,我想在多线程代码中使用此函数,因此我可以这样更改代码:
void foo(int i){
/* modify i */
}
Run Code Online (Sandbox Code Playgroud)
这肯定不会起作用,因为你只会修改一份副本i.如果您希望更改坚持,则需要传递int*或int&更改.
使用TLS肯定不会导致任何显着的开销(空间或时间)超过您实现相同功能可能遵循的任何自定义方法.实际上,编译器通过在保存线程局部变量的全局数据结构中动态分配存储"槽"来实现TLS.
当您在运行时访问线程局部变量时,会有一个额外的间接级别:首先,运行时必须访问当前线程的相应线程局部变量表,然后从表中获取值.使用数组中的索引(这是O(1)操作)完成此获取.
如果你打算这样做:
__thread int i;
void foo(void){
int *p = &i;
/* modify i using p pointer */
}
Run Code Online (Sandbox Code Playgroud)
那么就不需要i使用指针访问了.可以将其i视为一个全局变量,它对每个正在运行的线程都有不同的值.您不需要通过指针访问正常的全局来进行更改,因此也不需要使用带有线程局部变量的指针.
最后,线程局部存储并不是真正意味着每个线程存储大量变量(对TLS表的大小有依赖于编译器的限制),但这是你可以轻松解决的问题:将许多变量放入a struct和make中指向struct线程本地的指针.
| 归档时间: |
|
| 查看次数: |
8949 次 |
| 最近记录: |