自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一文看懂 C++ 線程管理:join、detach 傻傻分不清?

開發(fā)
如果只有一個工人要負(fù)責(zé)和面、烤制、包裝,效率會很低。但如果我們有多個工人同時工作,生產(chǎn)效率就會大大提高 - 這就是并發(fā)的魅力!

想象一個面包工廠的場景:如果只有一個工人要負(fù)責(zé)和面、烤制、包裝,效率會很低。但如果我們有多個工人同時工作,生產(chǎn)效率就會大大提高 - 這就是并發(fā)的魅力!

初識并發(fā)編程

讓我們先看看傳統(tǒng)的"單線程"工作方式:

#include <iostream>

int main() {
    std::cout << "一個工人要做所有工作..." << std::endl;
    std::cout << "和面 → 烤制 → 包裝" << std::endl;
    return 0;
}

現(xiàn)在讓我們用并發(fā)的方式來改進(jìn):

// ?? 引入必要的頭文件
#include <iostream>     // 用于輸入輸出
#include <thread>      // 用于創(chuàng)建和管理線程
#include <chrono>      // 用于時間相關(guān)操作

// ???? 和面師傅的工作流程
void make_dough() {
    std::cout << "工人A: 我負(fù)責(zé)和面! ??" << std::endl;
    // ?? 模擬和面需要的時間
    // sleep_for 讓線程暫停執(zhí)行一段時間
    std::this_thread::sleep_for(std::chrono::seconds(2));
}

// ???? 烘焙師傅的工作流程
void bake() {
    std::cout << "工人B: 我負(fù)責(zé)烤制! ??" << std::endl;
    // ? 模擬烤制過程所需時間
    // 這個過程比和面要久一些
    std::this_thread::sleep_for(std::chrono::seconds(3));
}

// ?? 工廠主要運(yùn)作流程
int main() {
    std::cout << "面包工廠開工! ??" << std::endl;
    
    // ?? 創(chuàng)建兩個工人線程
    // std::thread 對象一旦創(chuàng)建,新線程立即開始執(zhí)行
    std::thread worker1(make_dough);  // ???? 和面師傅開始工作
    std::thread worker2(bake);        // ???? 烘焙師傅開始工作
    
    // ?? 等待兩個工人完成他們的工作
    // join() 會阻塞主線程,直到工人線程完成工作
    worker1.join();  // 等待和面完成
    worker2.join();  // 等待烤制完成
    
    // ?? 所有工作完成
    std::cout << "今天的生產(chǎn)任務(wù)完成! ?" << std::endl;
    return0;
}

這個例子展示了并發(fā)編程的核心概念:

  • 每個工人(線程)專注于自己的任務(wù)
  • 工人們可以同時工作(并行執(zhí)行)
  • 最后等待所有工人完成工作(join)

這個例子中需要注意的關(guān)鍵點:

  • 線程同步問題(比如面包在烤好之前不能包裝)
  • 資源共享問題(比如多個工人共用一個烤箱)
  • 錯誤處理(比如某個工人生病了怎么辦)

這些問題我們接下來會詳細(xì)討論?,F(xiàn)在,你已經(jīng)理解了并發(fā)編程的基本概念! 

join 方法詳解

join() 這個名字來源于英文"加入"或"會合"的概念。就像約好在目的地會合一樣,主線程通過join() 等待并"會合"其他工作線程。

想象以下場景:

  • 主管(主線程)派出兩個工人(子線程)做不同的工作
  • 主管需要等待所有工人完成工作后,才能進(jìn)行下一步
  • 工人完成工作后,會與主管"會合"(join),匯報任務(wù)完成

join 的重要特性:

  • 阻塞性:調(diào)用 join() 的線程(通常是主線程)會被阻塞,直到被 join 的工作線程完成任務(wù)
  • 同步點:join() 創(chuàng)造了一個同步點,確保工作線程的任務(wù)已經(jīng)完成
  • 一次性:每個線程只能被 join 一次,重復(fù) join 會導(dǎo)致程序崩潰
  • 資源清理:join() 會清理線程相關(guān)的資源,防止資源泄露
// ?? join 使用示例
void example_join() {
    std::thread worker([]() {
        std::cout << "工人: 我在工作..." << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
    });
    
    std::cout << "主管: 等待工人完成工作..." << std::endl;
    worker.join();  // 主管在這里等待工人
    std::cout << "主管: 工人已完成工作,可以進(jìn)行下一步了!" << std::endl;
}

如果不使用 join:

  • 工作線程可能還沒完成任務(wù),程序就結(jié)束了
  • 可能導(dǎo)致資源泄露
  • 程序可能會異常崩潰

detach 方法詳解 - 放手去做

想象你養(yǎng)了一只獨立的貓咪 - 它不需要你時時刻刻看著,給它食物和水后它就能自己玩耍。detach() 就是這樣的概念!

// ?? 后勤清潔工的工作流程
// 這是一個永不停止的后臺任務(wù)
void cleanup() {
    while(true) {  // ?? 無限循環(huán) - 清潔工永遠(yuǎn)在崗
        std::cout << "后勤工人: 保持工作區(qū)整潔... ??" << std::endl;
        // ? 每5秒進(jìn)行一次清潔工作
        // 使用sleep避免CPU資源浪費
        std::this_thread::sleep_for(std::chrono::seconds(5));
    }
}

// ?? 工廠主要運(yùn)作流程
int main() {
    // ?? 創(chuàng)建清潔工線程
    std::thread cleaner(cleanup);
    
    // ??♂? detach()讓清潔工獨立工作
    // 這意味著:
    // 1. 主線程不會等待清潔工
    // 2. 清潔工會在后臺持續(xù)工作
    // 3. 程序結(jié)束時清潔工線程會自動終止
    cleaner.detach();  
    
    // ?? 主線程繼續(xù)其他工作
    std::cout << "生產(chǎn)繼續(xù)進(jìn)行,后勤工人在后臺默默工作" << std::endl;
    // ... 繼續(xù)生產(chǎn) ... 
    
    // ?? 注意: detach后的線程無法控制
    // 要小心使用detach,因為:
    // 1. 無法知道線程是否正常運(yùn)行
    // 2. 無法手動終止線程
    // 3. 資源可能無法正確釋放
}

使用 detach 要注意:

  • 就像放飛的氣球,一旦放手就抓不住了
  • 程序結(jié)束時會強(qiáng)制終止后臺線程
  • 要在 detach 前檢查線程是否可分離

最佳使用場景:

  • 后臺日志記錄
  • 數(shù)據(jù)自動保存
  • 狀態(tài)監(jiān)控任務(wù)

記?。翰皇撬芯€程都需要 join,有時候就該放手讓它飛~

資源競爭問題 ??♂? vs ??♀?

想象兩個面包師傅同時沖向最后一袋面粉的場景 - 這就是典型的資源競爭! 

為了避免"打架",我們需要一個"規(guī)則"(mutex互斥鎖)來確保同一時間只有一個師傅能使用面粉桶。就像在廁所門口掛個"使用中"的牌子一樣簡單! 

// ?? 互斥鎖: 就像面粉桶上的"使用中"標(biāo)志
// 防止多個面包師同時使用面粉,避免混亂
std::mutex flour_mutex;  

// ?? 面粉存量: 整個面包房共享的資源
// 1000克是我們的初始庫存
int flour_amount = 1000;  

void use_flour(int amount) {
    // ??? 智能鎖: 自動管理互斥鎖的加鎖和解鎖
    // 就像自動門,進(jìn)出面粉房時自動開關(guān)
    std::lock_guard<std::mutex> lock(flour_mutex);
    
    // ?? 檢查庫存是否充足
    if (flour_amount >= amount) {
        // ?? 更新庫存
        flour_amount -= amount;
        // ?? 記錄使用情況
        std::cout << "使用了 " << amount << "克面粉,還剩 " << flour_amount << "克" << std::endl;
    } else {
        // ?? 庫存不足警告
        std::cout << "糟糕,面粉不夠啦! ??" << std::endl;
    }
    // ?? 離開作用域時,lock_guard自動解鎖
    // 讓其他面包師可以使用面粉
}

有了這個智能的"使用中"牌子(lock_guard),我們再也不用擔(dān)心兩個師傅打架啦!它會自動幫我們管理上鎖和解鎖,就像一個盡職的小助手 - 即使發(fā)生異常也能確保面粉桶不會被永久鎖?。?nbsp;

同步問題

想象一個搞笑的場景:烤箱工人太急躁了,面團(tuán)還沒準(zhǔn)備好就想開始烤

為了避免這種尷尬,我們需要:

  • 互斥鎖:就像廁所的"占用"牌子
  • 條件變量:像個小鬧鐘,提醒烤箱工人"面團(tuán)好啦!"
  • 狀態(tài)標(biāo)志:簡單的"是/否"信號
// ?? 互斥鎖:控制對共享變量的訪問
std::mutex mtx;
// ?? 條件變量:用于線程間的通信和同步
std::condition_variable dough_ready;
// ?? 狀態(tài)標(biāo)志:表示面團(tuán)是否準(zhǔn)備就緒
bool is_dough_prepared = false;

// ???? 和面師傅的工作
void prepare_dough() {
    std::cout << "開始和面..." << std::endl;
    // ?? 模擬和面需要的時間
    std::this_thread::sleep_for(std::chrono::seconds(2));
    
    {
        // ??? 使用RAII方式加鎖,確保安全地更新共享變量
        std::lock_guard<std::mutex> lock(mtx);
        is_dough_prepared = true;
    }
    // ?? 通知烤箱工人面團(tuán)已經(jīng)準(zhǔn)備好
    dough_ready.notify_one();
}

// ???? 烤箱工人的工作
void bake_bread() {
    // ?? 使用unique_lock因為條件變量需要它
    std::unique_lock<std::mutex> lock(mtx);
    // ? 等待面團(tuán)準(zhǔn)備完成
    dough_ready.wait(lock, []{ return is_dough_prepared; });
    
    // ?? 收到通知,面團(tuán)已就緒
    std::cout << "面團(tuán)準(zhǔn)備好了,開始烤制!" << std::endl;
    // ?? 烤制過程 ...
}

就這么簡單!

  • 和面師傅完成后按鈴
  • 烤箱工人聽到鈴聲才開工
  • 完美配合,不會出岔子

實用技巧

1. RAII 線程管理大法

想象一下,你有一只調(diào)皮的小貓,它總是到處亂跑。ThreadGuard 就像是一個盡職的鏟屎官,幫你自動照看好這只小貓!

// ??? ThreadGuard: 線程守護(hù)者
// 使用 RAII 技術(shù)自動管理線程的生命周期
class ThreadGuard {
    // ?? 持有對線程的引用
    std::thread& t;
public:
    // ?? 構(gòu)造函數(shù): 接管線程的管理權(quán)
    explicit ThreadGuard(std::thread& t_) : t(t_) {}
    
    // ?? 析構(gòu)函數(shù): 確保線程正確結(jié)束
    ~ThreadGuard() {
        // ? 檢查線程是否可以join
        if(t.joinable()) {
            // ?? 自動join線程,防止線程懸空
            t.join();
        }
    }
    
    // ?? 禁用拷貝構(gòu)造函數(shù)
    // 防止多個對象管理同一個線程
    ThreadGuard(const ThreadGuard&) = delete;
    
    // ?? 禁用賦值運(yùn)算符
    // 確保線程管理權(quán)不會轉(zhuǎn)移
    ThreadGuard& operator=(const ThreadGuard&) = delete;
};

// ?? 使用示例:
void example() {
    std::thread worker([]() {
        // 執(zhí)行一些工作...
    });
    // ? 創(chuàng)建守護(hù)者,自動管理線程
    ThreadGuard guard(worker);
    // ?? 即使發(fā)生異常,guard析構(gòu)時也會確保worker被join
}

2. async 異步神器

還在為線程管理頭疼嗎?async 就是你的救星!就像叫外賣一樣簡單:

#include <future>  // ?? 引入異步編程支持

// ?? 使用async創(chuàng)建異步任務(wù) - 就像給面包房請了個臨時工
// std::launch::async 確保任務(wù)在新線程中執(zhí)行
auto future_bread = std::async(std::launch::async, []() {
    std::cout << "異步烤制面包中... ??" << std::endl;
    // ? 這里可以添加耗時操作,比如:
    // std::this_thread::sleep_for(std::chrono::seconds(3));
    return"新鮮出爐的面包 ??";
});

// ? 獲取異步任務(wù)的結(jié)果
// .get() 會等待任務(wù)完成 - 就像等待面包烤好
std::cout << future_bread.get() << " 準(zhǔn)備好了! ?" << std::endl;

// ?? 好處:
// 1. 不需要手動管理線程
// 2. 可以方便地獲取返回值
// 3. 異常會自動傳播
// 4. 智能地處理線程資源

記?。汉唵尉褪敲?,讓工具幫你干活,何必自己操心呢?

總結(jié)一下

本文帶你玩轉(zhuǎn) C++ 并發(fā)編程的核心概念:

  • 線程就像工人一樣,可以同時干活
  • join() 就像等待同事下班打卡
  • detach() 像放飛氣球,放手后就抓不住啦
  • mutex 就是廁所的"使用中"牌子
  • 條件變量像餐廳叫號器,到你了就通知你
  • RAII 是貼心小棉襖,自動管理資源
  • async 像叫外賣,又方便又省心

記?。翰l(fā)編程不可怕,關(guān)鍵是要用對工具!讓代碼飛起來~

責(zé)任編輯:趙寧寧 來源: everystep
相關(guān)推薦

2021-08-04 09:00:55

閉包Go調(diào)用

2022-05-05 13:54:37

SPI機(jī)制APISPI

2024-06-24 12:57:09

多線程C++編程語言

2021-03-10 08:56:37

Zookeeper

2021-01-22 08:37:02

二進(jìn)制Binary SemaReentrant L

2021-03-23 10:45:23

CookieSession前端

2021-05-09 21:57:08

數(shù)據(jù)倉庫Olap

2021-10-06 23:31:45

HibernateJPASpring Data

2021-08-02 12:50:45

sessiontokenJava

2024-02-29 09:08:56

Encoding算法加密

2020-07-13 09:16:04

Java集合

2021-07-27 07:31:16

JavaArrayList數(shù)組

2022-05-15 21:52:04

typeTypeScriptinterface

2022-12-07 07:38:07

存儲管理HSM

2020-03-31 14:40:24

HashMap源碼Java

2018-12-17 12:30:05

Kubernetes存儲存儲卷

2019-06-18 09:45:19

正向代理反向代理IT

2020-10-30 08:20:04

SD卡TF卡存儲

2022-04-15 11:47:47

LVSNginx負(fù)載均衡

2023-09-03 21:18:07

Python編程語言
點贊
收藏

51CTO技術(shù)棧公眾號