成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

震驚:這個 C++11 關鍵字讓多線程不再需要鎖?thread_local 實戰(zhàn)解密 !

開發(fā)
今天咱們聊一個看起來很"高大上"但其實超實用的 C++11 特性:thread_local關鍵字。

今天咱們聊一個看起來很"高大上"但其實超實用的 C++11 特性:thread_local關鍵字。我敢說,這可能是你寫多線程程序時最容易忽略,卻能一秒解決大麻煩的小技巧!

從一個真實的"故事"說起

前幾天一個 C++ 初學者求助我:"我寫的多線程程序結(jié)果總是錯的,找不到錯誤原因?"

我一看他貼出的代碼,立馬明白了問題所在:

// 全局變量,所有線程共享
int counter = 0;

void worker_function() {
    // 每個線程增加計數(shù)器100000次
    for (int i = 0; i < 100000; ++i) {
        counter++;  // 災難發(fā)生的地方!
    }
}

int main() {
    std::thread t1(worker_function);
    std::thread t2(worker_function);

    t1.join();
    t2.join();

    std::cout << "最終計數(shù): " << counter << std::endl;
    // 期望值:200000
    // 實際值:???(遠小于200000)

    return0;
}

這段代碼有什么問題?問題大了去了!多個線程同時讀寫同一個變量counter,沒有任何保護措施,必然導致數(shù)據(jù)競爭!

他撓撓頭問:"啊?這是什么意思?要怎么解決?加鎖嗎?"

我說:"加鎖當然可以,但是今天我要教你一招更酷的方式 —— thread_local!"

thread_local是什么神仙關鍵字?

簡單來說,thread_local就是告訴編譯器:"嘿,這個變量每個線程要有自己獨立的一份!"

它的特點就是:

  • 每個線程都有這個變量的獨立副本
  • 每個線程只能訪問自己的那份,互不干擾
  • 變量的生命周期與線程一樣長

聽起來是不是很像把變量變成了"個人財產(chǎn)",而不是大家一起"搶"的"公共資源"?

直觀感受:沒有thread_local VS 有thread_local

先看看沒用 thread_local 的情況:

#include <iostream>
#include <thread>
#include <vector>

// 普通全局變量 - 所有線程共享同一份
int global_counter = 0;

void increment_global(int id) {
    for (int i = 0; i < 1000; ++i) {
        global_counter++; // 多線程同時訪問,會出現(xiàn)數(shù)據(jù)競爭

        // 故意放慢速度,讓競爭更明顯
        if (i % 100 == 0) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    std::cout << "線程 " << id << " 完成,全局計數(shù): " << global_counter << std::endl;
}

int main() {
    std::vector<std::thread> threads;

    for (int i = 0; i < 5; ++i) {
        threads.push_back(std::thread(increment_global, i));
    }

    for (auto& t : threads) {
        t.join();
    }

    std::cout << "最終全局計數(shù): " << global_counter << std::endl;
    // 期望: 5000,實際: 遠小于5000

    return0;
}

運行結(jié)果:

線程 3 完成,全局計數(shù): 2986
線程 4 完成,全局計數(shù): 2986
線程 1 完成,全局計數(shù): 2986
線程 0 完成,全局計數(shù): 2986
線程 2 完成,全局計數(shù): 2986
最終全局計數(shù): 2986

看到了嗎?每個線程都增加了1000次,應該是5000,但實際只有2986,丟失了近2000多次增加操作!這就是數(shù)據(jù)競爭的后果!

再看使用 thread_local 的版本:

#include <iostream>
#include <thread>
#include <vector>

// 全局變量,但使用thread_local修飾
thread_localint local_counter = 0;
// 真正的全局變量,用于匯總
int total_counter = 0;

void increment_local(int id) {
    for (int i = 0; i < 1000; ++i) {
        local_counter++; // 每個線程操作自己的副本,沒有競爭

        // 故意放慢速度
        if (i % 100 == 0) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }

    // 結(jié)束時打印自己的計數(shù)值
    std::cout << "線程 " << id << " 完成,局部計數(shù): " << local_counter << std::endl;

    // 安全地將局部計數(shù)加到全局總數(shù)中(這里仍需要適當?shù)耐剑喕鹨娛÷?
    total_counter += local_counter;
}

int main() {
    std::vector<std::thread> threads;

    for (int i = 0; i < 5; ++i) {
        threads.push_back(std::thread(increment_local, i));
    }

    for (auto& t : threads) {
        t.join();
    }

    std::cout << "最終總計數(shù): " << total_counter << std::endl;
    // 期望: 5000,實際: 就是5000!

    return0;
}

運行結(jié)果:

線程 0 完成,局部計數(shù): 1000
線程 2 完成,局部計數(shù): 1000
線程 1 完成,局部計數(shù): 1000
線程 3 完成,局部計數(shù): 1000
線程 4 完成,局部計數(shù): 1000
最終總計數(shù): 5000

完美!每個線程都有自己的local_counter,互不干擾,最后加起來正好5000,一個都不少!

thread_local的內(nèi)部工作原理是啥?

說到原理,別被嚇著——其實很簡單!

想象一下,如果沒有 thread_local,變量就像一個公共停車位,所有線程都去那停車,必然打架。

而 thread_local 就像是給每個線程都發(fā)了一張停車卡,卡上寫著"專屬停車位:XX號"。這樣每個線程都有自己的專屬空間,自然就不會打架了。

技術上講,編譯器會為每個線程分配獨立的存儲空間來存放 thread_local 變量。當線程訪問這個變量時,實際上訪問的是分配給自己的那份副本。

thread_local真實案例:線程安全的單例模式

來看個實用例子,用 thread_local 實現(xiàn)線程安全的單例模式:

#include <iostream>
#include <thread>
#include <string>

class ThreadLogger {
private:
std::string prefix;

// 私有構(gòu)造函數(shù)
ThreadLogger(conststd::string& thread_name) : prefix("[" + thread_name + "]: ") {}

public:
// 獲取當前線程的日志實例
static ThreadLogger& getInstance(const std::string& thread_name) {
    // 每個線程都有自己的logger實例
    thread_local ThreadLogger instance(thread_name);
    return instance;
}

void log(const std::string& message) {
    std::cout << prefix << message << std::endl;
}
};

void worker(const std::string& name) {
    // 獲取當前線程的logger
    auto& logger = ThreadLogger::getInstance(name);

    logger.log("開始工作");
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    logger.log("工作中...");
    std::this_thread::sleep_for(std::chrono::milliseconds(300));
    logger.log("完成工作");
}

int main() {
    std::thread t1(worker, "線程1");
    std::thread t2(worker, "線程2");
    std::thread t3(worker, "線程3");

    t1.join();
    t2.join();
    t3.join();

    return0;
}

運行結(jié)果:

[線程1]: 開始工作
[線程2]: 開始工作
[線程3]: 開始工作
[線程1]: 工作中...
[線程2]: 工作中...
[線程3]: 工作中...
[線程1]: 完成工作
[線程2]: 完成工作
[線程3]: 完成工作

是不是很酷?每個線程都有自己專屬的日志對象,帶有自己的前綴,互不干擾!而且完全不需要加鎖,性能極佳!

thread_local的注意事項

話雖如此,使用 thread_local 也要注意一些坑:

  • 初始化時機:thread_local變量會在線程第一次使用它時初始化,不是在聲明時
  • 內(nèi)存消耗:每個線程都會分配空間,如果變量很大,多線程環(huán)境可能會消耗大量內(nèi)存
  • 不要濫用:并不是所有共享變量都需要thread_local,有時候簡單的互斥鎖更合適
  • 析構(gòu)時機:thread_local對象會在線程結(jié)束時析構(gòu),而不是程序結(jié)束時

小結(jié):thread_local到底好在哪?

總結(jié)一下 thread_local 的優(yōu)點:

  • 線程安全:不需要加鎖就能避免數(shù)據(jù)競爭
  • 性能更好:沒有鎖的開銷,訪問速度更快
  • 代碼簡潔:不需要寫復雜的同步代碼
  • 解決特定問題:某些場景(如線程ID、日志前綴等)用 thread_local 非常合適

最后的"靈魂拷問"

如果我問你:

  • 全局變量是什么?—— 整個程序共享一份
  • 局部變量是什么?—— 每個函數(shù)調(diào)用有一份
  • 那 thread_local 變量是什么?—— 每個線程有一份!

懂了吧?就是這么簡單!

下次當你看到多線程程序莫名其妙出問題,先想想是不是該用thread_local!一個關鍵字,省下一堆 debug 的時間,何樂而不為?

責任編輯:趙寧寧 來源: 跟著小康學編程
相關推薦

2023-09-22 22:27:54

autoC++11

2013-05-30 00:49:36

C++11C++條件變量

2023-09-24 13:58:20

C++1auto

2025-05-22 09:43:55

2017-05-27 20:59:30

Java多線程synchronize

2009-06-29 18:14:23

Java多線程volatile關鍵字

2013-07-31 11:09:05

C++11

2024-12-18 16:00:00

C++性能優(yōu)化consteval

2024-12-24 12:00:00

inlinC++17頭文件

2010-03-15 18:11:38

Java多線程

2020-07-17 20:15:03

架構(gòu)JMMvolatile

2009-09-02 09:24:03

C# this關鍵字

2009-08-21 14:58:56

C# this關鍵字

2019-12-20 15:19:41

Synchroinze線程安全

2009-06-29 18:26:11

Java多線程Synchronize同步類

2024-02-21 20:46:48

C++編程volatile

2009-08-13 13:04:29

C# lock關鍵字

2009-08-06 17:52:23

C#增加that關鍵字

2009-08-13 17:44:34

C# using關鍵字

2011-06-14 13:26:27

volatile
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 三级成人在线 | 精品欧美乱码久久久久久1区2区 | 久久久久久国产精品免费免费狐狸 | 中文字幕视频在线看 | 免费中文字幕日韩欧美 | 伊人看片| 亚洲国产高清高潮精品美女 | 欧美在线日韩 | 天天天操天天天干 | 国产精品久久久久久久久久久久冷 | 69堂永久69tangcom | 免费v片| 日韩中文字幕一区 | 国产成人a亚洲精品 | 操久久| 久久久久久久久99 | 一级片网站视频 | 国产成人jvid在线播放 | 久久99蜜桃综合影院免费观看 | 欧美精品久久久久 | 免费成人国产 | 我要看黄色录像一级片 | 人人草人人干 | 亚洲精品一区在线 | 久久99精品久久久久久国产越南 | 一区二区精品电影 | 中文字幕亚洲视频 | 夜夜草天天草 | 欧美日韩视频在线播放 | 99亚洲精品| 久久久国产亚洲精品 | 久久久久久av | 一区二区三区精品视频 | 色一级 | 91国内精精品久久久久久婷婷 | 日本网站在线看 | 欧美日韩一区精品 | 拍拍无遮挡人做人爱视频免费观看 | 久久综合一区二区 | 九九热免费观看 | 99国产精品一区二区三区 |