C++ threadlocal 和局部变量区别

文章讲述了`threadlocal`在多线程中的行为,强调了线程局部变量的独立副本特性,与全局变量的区别,以及如何通过`pthread_setspecific`和`pthread_getspecific`实现线程内部的全局变量。
摘要由CSDN通过智能技术生成

threadlocal 在代码中定义后,在不同的线程中会有不同的副本

先看代码

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <unistd.h>

thread_local unsigned int count = 1;
std::mutex cout_mutex; // 实际上这个锁没有用,下面代码不会发生争抢 count

void increase_count(const std::string& thread_name)
{
    ++count; // 在锁外修改 OK;这是线程局域变量; 线程安全; 是副本
    std::lock_guard<std::mutex> lock(cout_mutex);
    std::cout << "子线程 " << thread_name << ": " << count << '\n';
    std::cout << "count 地址" << &count << '\n'; // 证明 count 是副本
}

int main()
{
    std::thread a(increase_count, "a"), b(increase_count, "b");

    {
        sleep(1); // 为了让 main 函数的调用慢于 a、b 线程
        std::lock_guard<std::mutex> lock(cout_mutex);
        // 虽然 a、b 子线程先运行,都增加了 count 的值,但是主线程 count 的值依旧是 1
        std::cout << "主线程: " << count << '\n';
        std::cout << "count 地址" << &count << '\n';
    }

    a.join();
    b.join();
}

/*
子线程 a: 2
count 地址0x600001be4000
子线程 b: 2
count 地址0x600001bf8000
主线程: 1
count 地址0x600001be0000
*/

如果使用局部变量去写这个代码,应该是这样,不是完全等价,但是意思一样

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <unistd.h>

unsigned int count = 1; // 这个变量假设不会被其他线程修改
std::mutex cout_mutex; // 实际上这个锁没有用,下面代码不会发生争抢 count

void increase_count(const std::string& thread_name)
{
    unsigned int temp = count;
    temp++;
    std::lock_guard<std::mutex> lock(cout_mutex);
    std::cout << "子线程 " << thread_name << ": " << temp << '\n';
    std::cout << "count 地址" << &count << '\n'; // 全局变量 count 的地址一样
}

int main()
{
    std::thread a(increase_count, "a"), b(increase_count, "b");

    {
        sleep(1); // 为了让 main 函数的调用慢于 a、b 线程
        std::lock_guard<std::mutex> lock(cout_mutex);
        // 虽然 a、b 子线程先运行,都增加了 count 的值,但是主线程 count 的值依旧是 1
        std::cout << "主线程: " << count << '\n';
        std::cout << "count 地址" << &count << '\n';
    }

    a.join();
    b.join();
}

/*
子线程 a: 2
count 地址0x10268c000
子线程 b: 2
count 地址0x10268c000
主线程: 1
count 地址0x10268c000
*/

此外

如果真想定义线程内部的全局变量(线程内可见),建议参考 pthread_setspecific 和 pthread_getspecific

Linux线程私有数据Thread-specific Data(TSD) 详解_线程私有数据(thread specific data, tsd)_cheems~的博客-CSDN博客

通过一个 key 把变量存起来,又通过 key 把变量取出来,从而实现线程内部的全局变量 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值