线程本地存储(TLS)的学习

@原创文章,转载请注明: 转载自 镜中影的技术博客
本文链接地址: 线程本地存储(TLS)的学习)
URL:http://blog.csdn.net/linkpark1904/article/details/50790998

一、引言

最近在看jemalloc的文章 A Scalable Concurrent malloc(3) Implementation for FreeBSD, 文中有提到,在分配Arena的时候用到了线程本地存储技术(thread-local storage),这里发散一下,复习一下什么是线程本地存储。

二、简介

Thread-local storage,也就是在多线程程序中,为每个线程提供该线程独占的静态或者全局内存区域。说白了,也就是每个线程独享的全局变量。重所周知,在一个进程中,全局区的数据是被该进程的所有线程所共享的,而全局变量和静态变量位于内存地址空间中的全局数据区。然而,线程作为一个独立的执行体,能否有自己独有的全局变量呢?于是,就有了TLS技术。

三、示例

Windows下和Linux下对于线程本地存储的实现技术不同,所提供的接口也不一样。没关系,这里示例学习中,采用C++11。C++11将线程进行了封装,线程类位于中,示例代码如下:

#include 
#include 
#include 
#include 

using namespace std;

int var(0);
//thread_local int var(0);
std::mutex mtx;

void StartFunc() {
    std::unique_lock<std::mutex> lck (mtx);
    var++;
    cout << "Thread id:" <<  std::this_thread::get_id()
        << " var:" <int main() {
    for( int i = 0; i < 4; ++i ) {
        std::thread( StartFunc ).detach();
    }

    ::sleep(3);   
}

其中Thread对象就是C++11中已经封装好的线程类对象,接收一个函数名作为参数,创建一个线程,这里创建四个线程,分别对全局变量var 进行操作,结果可想而知:

执行结果

每个线程共享var变量,所以var变量是累加的。那么换成TSL变量呢?在c++11中,TSL变量很简单,C++11提供关键字thread_local,对于全局变量的生命,改成thread_local int var(0); 执行结果变为:
这里写图片描述

因为这个变量被每个线程独享,所以变量的值不会共享给其他的线程。

四、应用场景

那么问题来了,为什么会有TLS呢,举一个应用场景,对于errno的操作,如果errno是全局共享的,那么一个线程中错误码被设置了,那么很可能,这个错误码会被后面的一个线程给覆盖,这样,就没法拿到前一个线程的错误码了,所以,对于错误码errno,最好的方式是提供TLS,让每个线程都拥有自己的错误码,线程之间互不影响,一旦线程执行出错,就可以拿到这个线程的错误原因了。

你可能感兴趣的:(C++)