zoukankan      html  css  js  c++  java
  • TLS简介转

    1. 什么是TLS?
     
    TLS是Thread Local Storage(线程局部存储)的简称,是一项解决多线程内部变量使用问题的技术。用于将某些数据和一特定线程关联起来,即,这些数据为关联线程所独有(私有)。在多线程编程中, 同一个变量, 如果要让多个线程共享访问, 那么这个变量可以使用关键字volatile进行声明; 而如果一个变量不想被多个线程共享访问, 那么就应该使用TLS。
     
    2. 如何使用TLS编程?
     
    TLS使用非常简单, 只要对变量声明时使用__declspec(thread)修饰就可以了。例如:
     

    __declspec(thread) int g_nData = 0;

     
    3. 一个使用TLS的例子
     

     1 #include<windows.h> 
    2 #include<stdio.h>
    3
    4 #define THREADCOUNT 4
    5
    6 DWORD dwTlsIndex;
    7 int iNUM_OF_CALL_COMMON=0;
    8 int iNUM_OF_CALL_THREAD=0;
    9
    10 VOID ErrorExit(LPSTR);
    11
    12 VOID CommonFunc(VOID)
    13 {
    14 LPVOID lpvData;
    15 // Retrieve a data pointer for the current thread.
    16 iNUM_OF_CALL_COMMON++;
    17
    18 lpvData = TlsGetValue(dwTlsIndex);
    19 if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
    20 ErrorExit("TlsGetValue error");
    21
    22 // Use the data stored for the current thread.
    23 printf("common: thread %d: lpvData=%lx\n", GetCurrentThreadId(), lpvData);
    24 Sleep(5000);
    25 }
    26
    27 DWORD WINAPI ThreadFunc(VOID)
    28 {
    29 LPVOID lpvData;
    30
    31 // Initialize the TLS index for this thread.
    32 iNUM_OF_CALL_THREAD++;
    33 lpvData = (LPVOID) LocalAlloc(LPTR, 256);
    34 if (! TlsSetValue(dwTlsIndex, lpvData))
    35 ErrorExit("TlsSetValue error");
    36
    37 printf("thread %d: lpvData=%lx\n", GetCurrentThreadId(), lpvData);
    38 CommonFunc();
    39 // Release the dynamic memory before the thread returns.
    40 lpvData = TlsGetValue(dwTlsIndex);
    41 if (lpvData != 0)
    42 LocalFree((HLOCAL) lpvData);
    43 return 0;
    44 }
    45
    46 int main(VOID)
    47 {
    48 DWORD IDThread;
    49 HANDLE hThread[THREADCOUNT];
    50 int i;
    51
    52 // Allocate a TLS index.
    53 if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
    54 ErrorExit("TlsAlloc failed");
    55
    56 // Create multiple threads.
    57 for (i = 0; i < THREADCOUNT; i++)
    58 {
    59 hThread[i] = CreateThread(NULL, // default security attributes
    60 0, // use default stack size
    61 (LPTHREAD_START_ROUTINE) ThreadFunc, // thread function
    62 NULL, // no thread function argument
    63 0, // use default creation flags
    64 &IDThread); // returns thread identifier
    65
    66 // Check the return value for success.
    67 if (hThread[i] == NULL)
    68 ErrorExit("CreateThread error\n");
    69 }
    70
    71 // printf("All threads were created.\n");
    72 for (i = 0; i < THREADCOUNT; i++)
    73 WaitForSingleObject(hThread[i], INFINITE);
    74
    75 TlsFree(dwTlsIndex);
    76
    77 printf("The nums of thread is: %d\n",iNUM_OF_CALL_THREAD);
    78 printf("The nums of call is: %d\n",iNUM_OF_CALL_COMMON);
    79
    80 return 0;
    81 }
    82
    83 VOID ErrorExit (LPSTR lpszMessage)
    84 {
    85 fprintf(stderr, "%s\n", lpszMessage);
    86 ExitProcess(0);
    87 }

     
    4. T L S的内部数据结构
     
    名称:  1.jpg
查看次数: 484
文件大小:  20.5 KB

    图1 用于管理T L S的内部数据结构

     
     
    每个标志均可设置为FREE或者INUSE,表示TLS槽( s l o t )是否正在使用。Microsoft保证至少TLS_MINIMUM_AVAILABLE位标志是可供使用的。
     
    5. 相关API
     
    Windows TLS的API: TlsAlloc, TlsFree, TlsSetValue, TlsGetValue。
     
    ● DWORD TlsAlloc(); //(若要使用动态T L S,首先必须调用TlsAlloc函数)
     
    这个函数命令系统对进程中的位标志进行扫描,并找出一个FREE标志。然后系统将该标志从FREE改为INUSE,并且TlsAlloc返回位数组中的标志的索引。DLL(或APP)通常将该索引保存在一个全局变量中,因为它的值是每个进程而不是每个线程使用的值。
     
    ● BOOL TlsSetValue( //将一个值放入线程的数组中
     
    DWORD dwTlsIndex,
     
    PVOID pvTlsValue);
     
    ● PVOID TlsGetValue(DWORD dwTlsIndex); //要从线程的数组中检索一个值
     
    ● BOOL TlsFree(DWORD dwTlsIndex); //当在所有线程中不再需要保留TLS槽时
     
    参考资料:Jeffrey Richter《《Programming Applications for Microsoft Windows (4th Ed.)》》Chapter 21
     
    6. TLS目录
     
    名称:  7.JPG
查看次数: 485
文件大小:  82.7 KB
    TLS Callback Functions
    这是线程建立和退出时的回调函数, 包括主线程和其他线程.AddressOfCallBacks 是指向函数指针数组的指针, 以 0 结束. 
     
     typedef struct _TEB {
    NT_TIB Tib;
    PVOID EnvironmentPointer;
    CLIENT_ID Cid;
    PVOID ActiveRpcInfo;
    PVOID ThreadLocalStoragePointer; ; 2ch
    PPEB Peb; ; 30h
    ULONG LastErrorValue; ; 34h
    …}
     
    TLS目录 #define IMAGE_DIRECTORY_ENTRY_TLS 9 (第十个目录)

  • 相关阅读:
    CF 1083 A. The Fair Nut and the Best Path
    2434: [Noi2011]阿狸的打字机
    HDU 6086 Rikka with String
    HDU 2825 Wireless Password
    异常处理与补充模块
    面向对象
    初始socket
    面向对象的进阶(组合和继承)
    初始面向对象
    python之其他模块的用法
  • 原文地址:https://www.cnblogs.com/dsky/p/2355204.html
Copyright © 2011-2022 走看看