thread local storage

本文通过实例演示了如何使用线程局部存储(Thread Local Storage, TLS)来管理每个线程独有的数据,比较了C/C++中__thread关键字与Boost库中的thread_specific_ptr的不同实现方式,并展示了它们如何帮助避免线程间的数据竞争。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时会需要这种模式,一个全局变量,需要在程序的任何地方都可以使用它,但是当这个变量出现在不同线程时,就要求系统将这个变量拷贝到各个线程中,这样的话,每个线程内部也可以随时访问本线程的全局变量,但是线程之间的这个变量没有任何关系。这样就避免了锁,会提高程序运行的效率。在java中是ThreadLocal, 在boost中是

thread_specific_ptr。

在linux下C的方法是 _thread


//a.h
#ifndef __A_H
#define __A_H
#include <string>

using namespace std;
class A {
    public:
        string s;
        int i;
};


#endif


//c.h

#ifndef __C_H
#define __C_H
//#include <boost/thread/tss.hpp>
#include "a.h"
#include <pthread.h>
#include <unistd.h>
//using namespace boost;
class C {
    public:
        //static thread_specific_ptr<A> pool;
      static __thread A *pool;
      static void init() {
        pool = new A();
      }
    /*static __thread A *instance() {
        pool = new A();
        return pool;
    } */ 
};

__thread A *C::pool;
#endif


//list.h
#ifndef __LIST_H
#define __LIST_H
#include "c.h"
class list
{
    public:
        int start;
        int step;
        list(int s,int t):start(s), step(t){
            C::init();
            C::pool->i = s;
        }
        void inc() {
            C::pool->i += step;
        }

        int get() {
            return C::pool->i;
        }
};

#endif

//main.cpp

#include "c.h"
#include "list.h"
#include <iostream>
#include <pthread.h>
#include <unistd.h>

using namespace std;

int i = 1;
int s = 1;
void *run(void *junk) {
    list ls(i, s);
    for (int ind = 0; ind < 10; ++ind) {
        cout << (size_t)pthread_self() << ": "<< ls.get()<<endl;
        ls.inc();
        sleep(2);

      //  cout << (size_t)pthread_self() << ": "<< ls.get()<<endl;
    }

}

int main() {
    pthread_t t_a, t_b;
    pthread_create(&t_a, NULL, run, (void *)NULL);
    sleep(2);

    i += 1000;
    s = 5;
    pthread_create(&t_b, NULL, run, (void*)NULL);

    pthread_join(t_a, NULL);
    pthread_join(t_b, NULL);
    return 0;
}


g++ -lpthread  main.cpp -o test


output:

1085499712: 1
1095989568: 1001
1085499712: 2
1095989568: 1006
1085499712: 3
1095989568: 1011
1085499712: 4
1095989568: 1016
1085499712: 5
1095989568: 1021
1085499712: 6
1095989568: 1026
1085499712: 7
1095989568: 1031
1085499712: 8
1095989568: 1036
1085499712: 9
1095989568: 1041
1085499712: 10
1095989568: 1046


如果将c.h中的__thread都注释掉的,数据就不一致了:

1110722880: 1
1110722880: 2
1121212736: 1001
1121212736: 1006
1110722880: 1011
1121212736: 1012
1110722880: 1017
1121212736: 1018
1110722880: 1023
1121212736: 1024
1110722880: 1029
1121212736: 1030
1110722880: 1035
1121212736: 1036
1110722880: 1041
1121212736: 1042
1110722880: 1047
1121212736: 1048
1110722880: 1053
1121212736: 1054



如果用boost,更简单


//c.h
#ifndef __C_H
#define __C_H
#include <boost/thread/tss.hpp>
#include "a.h"
#include <pthread.h>
#include <unistd.h>
using namespace boost;
class C {
    public:
      static thread_specific_ptr<A> pool;
      //static __thread A *pool;
      //static void init() {
      //  pool = new A();
     // }
    /*static __thread A *instance() {
        pool = new A();
        return pool;
    } */ 
};

thread_specific_ptr<A> C::pool;
//__thread A *C::pool;
#endif

// list.h 
#ifndef __LIST_H
#define __LIST_H
#include "c.h"
class list
{
    public:
        int start;
        int step;
        list(int s,int t):start(s), step(t){
            //C::init();

            C::pool.reset(new A);
            C::pool->i = s;
        }
        void inc() {
            C::pool->i += step;
        }

        int get() {
            return C::pool->i;
        }
};

#endif

g++ main.cpp -I~/boost -lboost_thread -lpthread -o test



1086380352: 1
1117477184: 1001
1086380352: 2
1117477184: 1006
1086380352: 3
1117477184: 1011
1086380352: 4
1117477184: 1016
1086380352: 5
1117477184: 1021
1086380352: 6
1117477184: 1026
1086380352: 7
1117477184: 1031
1086380352: 8
1117477184: 1036
1086380352: 9
1117477184: 1041
1086380352: 10
1117477184: 1046



http://www.searchtb.com/2012/09/tls.html

此博客也介绍了线程局部变量的对比,至于__thread容易造成内存泄露,不是很明白


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值