Windows Programming系列 线程本地存储器

1、如果你的应用程序需要严重依赖全局变量或静态变量,那么T L S能够帮助解决它遇到的问题。但是编程人员往往尽可能减少对这些变量的使用,而更多地依赖自动(基于堆栈的)变量和通过函数的参数传递的数据。这样做是很好的,因为基于堆栈的变量总是与特定的线程相联系的。

2、在我的软件开发项目中,我总是尽可能避免使用全局变量和静态变量。如果你的应用程序使用全局变量和静态变量,那么建议你务必观察每个变量,并且了解一下它能否改变成基于堆栈的变量。如果打算将线程添加给应用程序,那么这样做可以节省大量时间,甚至单线程应用程序也能够从中得到许多好处。 

3、静态TLS

  • 动态TLS和静态TLS都能够将数据与线程联系起来。但是,静态TLS在代码中使用起来要容易得多,因为不必调用任何函数就能够使用它。
  • __declspec(thread) DWORD gt_dwStartTime = 0;__declspec(thread)的前缀是Microsoft添加给Visual C++编译器的一个修改符。它告诉编译器,对应的变量应该放入可执行文件或DLL文件中它的自己的节中。__declspec(thread)后面的变量必须声明为函数中(或函数外)的一个全局变量或静态变量。不能声明一个类型为__declspec(thread)的局部变量。这不应该是个问题,因为局部变量总是与特定的线程相联系的。我将前缀g t _用于全局T L S变量,而将s t _用于静态T L S变量。
  • 如果在进程中创建了另一个线程,那么系统就要将它捕获并且自动分配另一个内存块,以便存放新线程的静态TLS变量。新线程只拥有对它自己的静态TLS变量的访问权,不能访问属于其他线程的TLS变量。
  • 下面让我们来看一下当应用程序调用L o a d L i b r a r y,以便链接到也包含静态T L S变量的一个D L L时,将会发生什么情况。系统必须查看进程中已经存在的所有线程,并扩大它们的T L S内存块,以便适应新D L L对内存的需求。另外,如果调用F r e e L i b r a r y来释放包含静态T L S变量的D L L,那么与进程中的每个线程相关的的内存块应该被压缩。
4、动态TLS
  • DWORD TlsAlloc();TlsAlloc会对数组元素进行初始化
  • BOOL TlsSetValue(DWORD dwTlsIndex, PVOID pvTlsValue);
  • PVOID TlsGetValue(DWORD dwTlsIndex);
  • BOOL TlsFree(DWORD dwTlsIndex);
5、使用动态TLS
 
 
DWORD g_dwTlsIndex;  //  Assume that this is initialized
                    
//  with the result of a call to TlsAlloc.


void  MyFunction(PSOMESTRUCT pSomeStruct)
{
   
if (pSomeStruct != NULL)
   
{
      
// The caller is priming this function.

      
// See if we already allocated space to save the data.
      if (TlsGetValue(g_dwTlsIndex) == NULL) 
      
{
         
//Space was never allocated. This is the first
         
//time this function has ever been called by this thread.
         TlsSetValue(g_dwTlsIndex,
            HeapAlloc(GetProcessHeap(), 
0sizeof(*pSomeStruct));
      }


      
// Memory already exists for the data;
      
// save the newly passed values.
      memcpy(TlsGetValue(g_dwTlsIndex), pSomeStruct,
         
sizeof(*pSomeStruct));

   }
 
   
else
   
{

      
// The caller already primed the function. Now it
      
// wants to do something with the saved data.

      
// Get the address of the saved data.
      pSomeStruct = (PSOMESTRUCT) TlsGetValue(g_dwTlsIndex);

      
// The saved data is pointed to by pSomeStruct; use it.
      ...
   }

如果你的应用程序的线程从来不调用MyFunction,那么也就从来不用为该线程分配内存块。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值