首页
社区
课程
招聘
[求助]请教下,TLS是用来做什么的。
发表于: 2009-5-13 09:42 6031

[求助]请教下,TLS是用来做什么的。

2009-5-13 09:42
6031
请教下,TLS是用来做什么的。
在学习多线程编程,线程同步搞的很晕,搞不懂TLS可以干什么,网上查到
“Thread Local Storage的功用是什么呢?它主要是为了避免多个线程同时访存同一全局变量或者静态变量时所导致的冲突,尤其是多个线程同时需要修改这一变量时。为了解决这个问题,我们可以通过TLS机制,为每一个使用该全局变量的线程都提供一个变量值的副本,每一个线程均可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。而从全局变量的角度上来看,就好像一个全局变量被克隆成了多份副本,而每一份副本都可以被一个线程独立地改变。”
如果是被克隆了多个副本,不就是相当于没有变量共享,都是线程自己的私有变量就可以了?

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 354
活跃值: (157)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
2
我的一点认识:
TLS线程局部存储,用于存储线程局部数据。TLS机制为进程中每个线程关联若干个数据。各个线程通过TLS 分配的全局索引来访问自己关联的数据。
Windows为每一个进程维护了一个数组,进程中每个线程又有一个对应数组,进程的数组用来指示线程数组中哪一个成员在使用中。线程数组则保存自己的数据。
这是王艳平书上一个例子,斑竹看下吧。欲知详情,请看《windows程序设计》(王艳平)
#include <stdio.h>
#include <windows.h>
#include <process.h>

// 利用TLS记录线程的运行时间

DWORD g_tlsUsedTime;
void InitStartTime();
DWORD GetUsedTime();

UINT __stdcall ThreadFunc(LPVOID)
{
        int i;

        // 初始化开始时间
        InitStartTime();

        // 模拟长时间工作
        i = 10000*10000;
        while(i--) { }

        // 打印出本线程运行的时间
        printf(" This thread is coming to end. Thread ID: %-5d, Used Time: %d \n",
                                                ::GetCurrentThreadId(), GetUsedTime());
        return 0;
}

int main(int argc, char* argv[])
{
        UINT uId;
        int i;
        HANDLE h[10];

        // 通过在进程位数组中申请一个索引,初始化线程运行时间记录系统
        g_tlsUsedTime = ::TlsAlloc();

        // 令十个线程同时运行,并等待它们各自的输出结果
        for(i=0; i<10; i++)
        {
                h[i] = (HANDLE)::_beginthreadex(NULL, 0, ThreadFunc, NULL, 0, &uId);
        }
        for(i=0; i<10; i++)
        {
                ::WaitForSingleObject(h[i], INFINITE);
                ::CloseHandle(h[i]);
        }

        // 通过释放线程局部存储索引,释放时间记录系统占用的资源
        ::TlsFree(g_tlsUsedTime);
        return 0;
}

// 初始化线程的开始时间
void InitStartTime()
{
        // 获得当前时间,将线程的创建时间与线程对象相关联
        DWORD dwStart = ::GetTickCount();
        ::TlsSetValue(g_tlsUsedTime, (LPVOID)dwStart);
}

// 取得一个线程已经运行的时间
DWORD GetUsedTime()
{
        // 获得当前时间,返回当前时间和线程创建时间的差值
        DWORD dwElapsed = ::GetTickCount();
        dwElapsed = dwElapsed - (DWORD)::TlsGetValue(g_tlsUsedTime);
        return dwElapsed;
}
2009-5-13 10:12
0
雪    币: 221
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
应该是为了防止线程对全局或静态变量做不必要的修改而提供变量的副本 这样线程所做的操作就不能影响到全局静态变量   要达到共享目的的话可以就不用这样做了吧
2009-5-13 11:02
0
雪    币: 53
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
线程绑定的数据..
2009-5-13 13:25
0
雪    币: 2316
活跃值: (129)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
5
多谢。还是有点晕。
例子中,用线程自己的变量不可以实现吗?为什么要用TLS?执行起来有什么区别吗?
2009-5-13 18:29
0
雪    币: 264
活跃值: (11)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
6
只知道可以比OEP早运行 干点萎缩的勾当..
2009-5-13 18:36
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
理解的简单点就是原来单线程的全局变量,在线程内部作用同原来是一样的,可以放标志位,可以放缓冲的指针等等

线程间共享引入超级全局变量,有可能需要用锁之类的保护,当然也有例外,如单读单写的循环队列
2009-5-13 20:05
0
雪    币: 354
活跃值: (157)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
线程自己的变量?说的就是线程局部变量,用自己的变量你试试,上面 的程序你又得写不少代码,TLS的关键在于系统内部把局部变量和线程关联起来,线程只能访问自己关联的数据,这样就很方便了。
2009-5-14 16:21
0
雪    币: 209
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
多线程的C运行库与之前的AnsiC运行库有了很大不同,很大程度上就是因为多线程需要各线程之间访问全局变量时不发生冲突,因此需要TLS,否则像rand()这些函数运行结果是不同的,可以看_tiddata的结构。Jeffry Richer 的文章。
2009-5-15 00:14
0
雪    币: 2056
活跃值: (13)
能力值: ( LV13,RANK:250 )
在线值:
发帖
回帖
粉丝
10
Windows核心编程第21章。
2009-5-15 10:15
0
游客
登录 | 注册 方可回帖
返回
//