zoukankan      html  css  js  c++  java
  • 线程局部存储 TLS

    C/C++运行库提供了TLS(线程局部存储),在多线程还未产生时,可以将数据与正在执行的线程关联。strtok()函数就是一个很好的例子。与它一起的还有strtok_s(),_tcstok_s()等等函数,其实_tcs 是 wcs 的另外一种写法,表示宽字符存储,_s 是微软定义的安全函数,通常比普通函数多一个参数。以_tcstok_s()为例,

    int main(int argc, char* argv[])
    {

    wchar_t Source[] = L"192.168.255.255";
    wchar_t doc[] = L".";
    wchar_t* next_token;
    wchar_t* Dest = _tcstok_s(Source, doc, &next_token); //strtok_s
    int i = 1;
    while (Dest != NULL)
    {
    printf("Dest[%d]: %S\r\n", i, Dest);
    Dest = _tcstok_s(NULL, doc, &next_token);
    i++;
    }
    return 0;
    }

    如果提示函数不认识,添加头文件 #include <tchar.h>

    代码很简单,将源字符串以 “.”为分隔符分开,并输出。注意第二次调用_tcstok_s函数时,第一参数传NULL,这是因为第一次调用时已经将字符串保存在自己的静态变量中,后面再使用就可以引用保存的地址。

    但在多线程编程下,第一个线程调用_tcstok_s,当它再次调用之前,另一个线程也可能调用它。这样就导致第一次的内容被覆盖。这就用到TLS的内容了。

    1.静态TLS

    #include "stdafx.h"
    #include <windows.h>
    #include <iostream>
    using namespace std;

    __declspec(thread)  int value  = 0;

    DWORD WINAPI ThreadProc(LPVOID Param);

    int main(int argc, char* argv[])
    {
    value = 1;
    HANDLE ThreadHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);

    WaitForSingleObject(ThreadHandle, INFINITE);

    cout << "main " << value << endl;
    return 0;
    }

    DWORD WINAPI ThreadProc(LPVOID Param)
    {
    value = 10;
    cout << value << endl;
    return 0;
    }

    __declspec(thread)  这个修饰符告诉编译器,将这个值放在.tls段中,如果不写,会放在.data段里。

    结果:

    定义了__declspec(thread)     输出 10           main 1

    没定义__declspec(thread)     输出 10           main 10

    2.动态TLS

    #include "stdafx.h"
    #include <windows.h>
    #include <iostream>
    using namespace std;

    int __Index[3] = { 0 };
    char Name[3][20] = { {"qwe"},{"asd"},{"zxc"} };
    DWORD WINAPI ThreadProc(LPVOID Param);

    int main(int argc, char* argv[])
    {
    int i = 0;
    DWORD ThreadID[3] = { 0 };
    HANDLE ThreadHandle[3] = { 0 };
    for (; i < 3; i++)
    {
    __Index[i] = TlsAlloc();  // 对位标志进行检索,找到一个FREE标志,其实就是预定了一个索引
    if (__Index[i] <= TLS_MINIMUM_AVAILABLE) 
    {
    ThreadHandle[i] = CreateThread(NULL, 0, ThreadProc, (LPVOID)(Name[i]), 0, &ThreadID[i]);
    }
    }
    WaitForMultipleObjects(3, ThreadHandle, TRUE, INFINITE);
    return 0;
    }

    DWORD WINAPI ThreadProc(LPVOID Param)
    {
    char* key = new char[20];
    memcpy(key, (char*)Param, 20);
    TlsSetValue(__Index[0], key);   //将值与索引关联,注意,微软实现它时,牺牲了错误检查,即使错误的索引,也会分配
    for (int i = 0; i < 10; i++)
    {
    Sleep(1);
    printf("%s\r\n", (char*)TlsGetValue(__Index[0]));    // 返回 索引中的值

    }

    free(key);
    return 0;
    }

     一般来说,这两种TLS在创建DLL时更加有用。

  • 相关阅读:
    UVA 11806 组合数学+容斥
    Educational Codeforces Round 37 (Rated for Div. 2) G
    java 5 线程池
    团队-象棋游戏-项目进度
    结对-五子棋-测试过程
    结对-五子棋游戏-开发过程
    课后作业-阅读任务-阅读提问-2
    20171006-构建之法:现代软件工程-阅读笔记
    结队-五子棋游戏-项目进度
    团队-象棋游戏-代码设计规范
  • 原文地址:https://www.cnblogs.com/kekoukele987/p/7301309.html
Copyright © 2011-2022 走看看