最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中fork()函數(shù)

 更新時(shí)間:2026年03月27日 09:47:05   作者:Ralph_Y  
fork()是Unix/Linux下創(chuàng)建子進(jìn)程的核心系統(tǒng)調(diào)用,調(diào)用一次返回兩次,本文就來詳細(xì)的介紹一下C++中fork()函數(shù)的使用,感興趣的可以了解一下

一、fork函數(shù)核心概念

fork() 是Unix/Linux系統(tǒng)下的系統(tǒng)調(diào)用(C++可通過<unistd.h>頭文件調(diào)用),核心作用是創(chuàng)建一個(gè)新進(jìn)程(子進(jìn)程),原進(jìn)程稱為父進(jìn)程。

關(guān)鍵特性(新手必懂)

  • 調(diào)用一次,返回兩次fork() 調(diào)用后,操作系統(tǒng)會(huì)復(fù)制父進(jìn)程的內(nèi)存空間(代碼、數(shù)據(jù)、堆棧、文件描述符等),形成子進(jìn)程。因此:
    • 父進(jìn)程中,fork() 返回子進(jìn)程的PID(進(jìn)程ID,非負(fù)整數(shù));
    • 子進(jìn)程中,fork() 返回0;
    • 若創(chuàng)建失?。ㄈ缦到y(tǒng)進(jìn)程數(shù)上限),返回**-1**。
  • 寫時(shí)復(fù)制(Copy-On-Write, COW):現(xiàn)代系統(tǒng)不會(huì)立即復(fù)制全部內(nèi)存,而是讓父子進(jìn)程共享內(nèi)存頁,僅當(dāng)某一方修改數(shù)據(jù)時(shí)才復(fù)制對應(yīng)頁面,大幅提升效率。
  • 執(zhí)行流分離:父子進(jìn)程從fork()的下一行代碼開始并行執(zhí)行,但調(diào)度順序由操作系統(tǒng)決定,無法預(yù)測。

二、基本用法與代碼示例

1. 最簡示例(區(qū)分父子進(jìn)程)

#include <iostream>
#include <unistd.h>   // fork() 頭文件
#include <sys/wait.h> // wait() 頭文件
#include <cstdlib>    // exit() 頭文件
int main() {
    // 調(diào)用fork創(chuàng)建子進(jìn)程
    pid_t pid = fork();
    // 錯(cuò)誤處理:fork失敗
    if (pid == -1) {
        std::cerr << "fork failed!" << std::endl;
        exit(EXIT_FAILURE);
    }
    // 子進(jìn)程分支(pid == 0)
    else if (pid == 0) {
        std::cout << "子進(jìn)程:PID = " << getpid() 
                  << ",父進(jìn)程PID = " << getppid() << std::endl;
        // 子進(jìn)程執(zhí)行完退出,避免繼續(xù)執(zhí)行后續(xù)代碼
        exit(EXIT_SUCCESS);
    }
    // 父進(jìn)程分支(pid > 0)
    else {
        std::cout << "父進(jìn)程:PID = " << getpid() 
                  << ",創(chuàng)建的子進(jìn)程PID = " << pid << std::endl;
        // 父進(jìn)程等待子進(jìn)程結(jié)束,避免子進(jìn)程變成“僵尸進(jìn)程”
        wait(NULL); 
        std::cout << "子進(jìn)程已退出" << std::endl;
    }
    return 0;
}

2. 代碼解釋

  • pid_t:專門存儲(chǔ)進(jìn)程ID的類型(本質(zhì)是整型);
  • getpid():獲取當(dāng)前進(jìn)程的PID;
  • getppid():獲取當(dāng)前進(jìn)程的父進(jìn)程PID;
  • wait(NULL):父進(jìn)程阻塞等待任意子進(jìn)程退出,回收子進(jìn)程資源;
  • exit(EXIT_SUCCESS):子進(jìn)程顯式退出,保證邏輯清晰。

3. 運(yùn)行結(jié)果示例

父進(jìn)程:PID = 1234,創(chuàng)建的子進(jìn)程PID = 1235
子進(jìn)程:PID = 1235,父進(jìn)程PID = 1234
子進(jìn)程已退出

(注:父子進(jìn)程輸出順序可能互換,取決于系統(tǒng)調(diào)度。)

三、常見使用場景

  1. 并發(fā)執(zhí)行任務(wù):父進(jìn)程處理主邏輯,子進(jìn)程處理耗時(shí)/獨(dú)立任務(wù)(如文件讀寫、網(wǎng)絡(luò)請求);
  2. 守護(hù)進(jìn)程創(chuàng)建:通過兩次fork()脫離終端,成為后臺(tái)守護(hù)進(jìn)程;
  3. 多進(jìn)程服務(wù)器:父進(jìn)程監(jiān)聽端口,每接收到一個(gè)客戶端連接就fork()子進(jìn)程處理該連接。

四、注意事項(xiàng)(新手易踩坑)

  1. 僵尸進(jìn)程問題:若父進(jìn)程不調(diào)用wait()/waitpid()等待子進(jìn)程退出,子進(jìn)程退出后資源無法回收,會(huì)變成僵尸進(jìn)程(可通過ps -ef | grep defunct查看);
  2. 孤兒進(jìn)程問題:若父進(jìn)程先于子進(jìn)程退出,子進(jìn)程會(huì)被init進(jìn)程(PID=1)接管,成為孤兒進(jìn)程(通常無危害);
  3. 資源共享與競爭:父子進(jìn)程共享文件描述符,但私有內(nèi)存空間;若需通信,需用管道、共享內(nèi)存等IPC機(jī)制;
  4. 信號處理fork()后子進(jìn)程會(huì)繼承父進(jìn)程的信號處理方式,但未處理的信號會(huì)被重置。

五、進(jìn)階示例:循環(huán)創(chuàng)建多個(gè)子進(jìn)程

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <cstdlib>
int main() {
    const int child_num = 3; // 創(chuàng)建3個(gè)子進(jìn)程
    for (int i = 0; i < child_num; ++i) {
        pid_t pid = fork();
        if (pid == -1) {
            std::cerr << "fork failed!" << std::endl;
            exit(EXIT_FAILURE);
        } else if (pid == 0) {
            // 子進(jìn)程:打印自身編號和PID
            std::cout << "子進(jìn)程" << i+1 << ":PID = " << getpid() << std::endl;
            exit(EXIT_SUCCESS); // 關(guān)鍵:子進(jìn)程退出,避免繼續(xù)循環(huán)創(chuàng)建孫進(jìn)程
        }
    }
    // 父進(jìn)程:等待所有子進(jìn)程退出
    for (int i = 0; i < child_num; ++i) {
        wait(NULL);
    }
    std::cout << "所有子進(jìn)程已退出" << std::endl;
    return 0;
}

總結(jié)

  1. fork() 是Unix/Linux下創(chuàng)建子進(jìn)程的核心系統(tǒng)調(diào)用,調(diào)用一次返回兩次(父進(jìn)程返回子PID,子進(jìn)程返回0);
  2. 核心特性包括寫時(shí)復(fù)制、執(zhí)行流并行、資源繼承(文件描述符)與私有(內(nèi)存);
  3. 使用時(shí)需注意回收子進(jìn)程資源(避免僵尸進(jìn)程)、區(qū)分父子執(zhí)行邏輯、處理進(jìn)程間通信需求。

一、進(jìn)程間通信(IPC)核心機(jī)制詳解

fork()創(chuàng)建的父子進(jìn)程中,由于內(nèi)存空間完全私有(寫時(shí)復(fù)制僅延遲復(fù)制,最終仍是獨(dú)立空間),需通過專門的IPC機(jī)制實(shí)現(xiàn)數(shù)據(jù)交互。以下是最常用的管道、共享內(nèi)存,以及補(bǔ)充的其他核心IPC機(jī)制:

1. 管道(Pipe)—— 最簡單的單向通信

管道是半雙工(單向)的通信通道,分為匿名管道和命名管道兩類,核心是基于文件描述符的字節(jié)流傳輸。

(1)匿名管道(Pipe)

  • 核心特點(diǎn):僅適用于有親緣關(guān)系的進(jìn)程(如父子/兄弟進(jìn)程),隨進(jìn)程退出自動(dòng)銷毀,無文件名,僅存在于內(nèi)核中。
  • 創(chuàng)建方式:通過pipe()系統(tǒng)調(diào)用創(chuàng)建,返回兩個(gè)文件描述符:fd[0](讀端)、fd[1](寫端)。
  • 通信邏輯
    1. 父進(jìn)程調(diào)用pipe()創(chuàng)建管道;
    2. 父進(jìn)程fork()子進(jìn)程,子進(jìn)程繼承管道的文件描述符;
    3. 父進(jìn)程關(guān)閉讀端(或?qū)懚耍?,子進(jìn)程關(guān)閉寫端(或讀端),形成單向傳輸;
    4. 數(shù)據(jù)通過write()寫入管道,read()從管道讀?。ü艿罏榭諘r(shí)read()阻塞,滿時(shí)write()阻塞)。
  • 代碼示例(父子進(jìn)程管道通信)
#include <iostream>
#include <unistd.h>
#include <cstring>
#include <sys/wait.h>
int main() {
    int fd[2];
    // 創(chuàng)建匿名管道
    if (pipe(fd) == -1) {
        perror("pipe failed");
        return 1;
    }
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork failed");
        return 1;
    }
    if (pid == 0) { // 子進(jìn)程:讀數(shù)據(jù)
        close(fd[1]); // 關(guān)閉寫端
        char buf[100];
        ssize_t bytes_read = read(fd[0], buf, sizeof(buf)-1);
        if (bytes_read > 0) {
            buf[bytes_read] = '\0';
            std::cout << "子進(jìn)程讀取到:" << buf << std::endl;
        }
        close(fd[0]); // 讀完關(guān)閉讀端
        return 0;
    } else { // 父進(jìn)程:寫數(shù)據(jù)
        close(fd[0]); // 關(guān)閉讀端
        const char* msg = "Hello from parent process!";
        write(fd[1], msg, strlen(msg));
        close(fd[1]); // 寫完關(guān)閉寫端
        wait(NULL); // 等待子進(jìn)程
        std::cout << "父進(jìn)程完成通信" << std::endl;
    }
    return 0;
}
  • 適用場景:父子進(jìn)程間簡單的單向數(shù)據(jù)傳輸(如父進(jìn)程給子進(jìn)程傳遞配置、子進(jìn)程給父進(jìn)程返回結(jié)果)。

(2)命名管道(FIFO)

  • 核心特點(diǎn):適用于無親緣關(guān)系的進(jìn)程,以文件形式存在于文件系統(tǒng)中(有路徑和文件名),數(shù)據(jù)仍存儲(chǔ)在內(nèi)核,讀寫方式與普通文件一致。
  • 創(chuàng)建方式:通過mkfifo()函數(shù)或mkfifo命令創(chuàng)建(如mkfifo /tmp/myfifo)。
  • 通信邏輯:進(jìn)程A打開FIFO文件寫入數(shù)據(jù),進(jìn)程B打開同一FIFO文件讀取數(shù)據(jù),實(shí)現(xiàn)跨進(jìn)程通信。
  • 關(guān)鍵區(qū)別:匿名管道僅用于親緣進(jìn)程,F(xiàn)IFO可用于任意進(jìn)程;兩者均遵循“先進(jìn)先出”(FIFO)規(guī)則。

2. 共享內(nèi)存(Shared Memory)—— 最快的IPC機(jī)制

共享內(nèi)存是讓多個(gè)進(jìn)程直接訪問同一塊物理內(nèi)存區(qū)域,無需數(shù)據(jù)拷貝(管道/消息隊(duì)列需內(nèi)核拷貝),是效率最高的IPC方式。

  • 核心特點(diǎn)
    1. 內(nèi)存區(qū)域由內(nèi)核創(chuàng)建,映射到多個(gè)進(jìn)程的虛擬地址空間;
    2. 進(jìn)程直接讀寫該內(nèi)存,無需系統(tǒng)調(diào)用轉(zhuǎn)發(fā)(僅初始化時(shí)需調(diào)用);
    3. 無內(nèi)置同步機(jī)制,需配合信號量(Semaphore)/互斥鎖(Mutex)避免數(shù)據(jù)競爭。
  • 創(chuàng)建與使用步驟
    1. 父進(jìn)程通過shmget()創(chuàng)建共享內(nèi)存段(指定鍵值、大小、權(quán)限);
    2. 通過shmat()將共享內(nèi)存映射到自身虛擬地址空間;
    3. fork()子進(jìn)程,子進(jìn)程繼承映射關(guān)系(或其他進(jìn)程通過相同鍵值連接);
    4. 進(jìn)程讀寫共享內(nèi)存,通過信號量同步;
    5. 通信結(jié)束后,shmdt()解除映射,shmctl()刪除共享內(nèi)存段。
  • 代碼示例(父子進(jìn)程共享內(nèi)存)
#include <iostream>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <cstring>

#define SHM_KEY 1234 // 共享內(nèi)存鍵值(唯一標(biāo)識)
#define SHM_SIZE 1024 // 共享內(nèi)存大小

int main() {
    // 創(chuàng)建共享內(nèi)存段
    int shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | 0666);
    if (shmid == -1) {
        perror("shmget failed");
        return 1;
    }

    // 將共享內(nèi)存映射到進(jìn)程地址空間
    char* shm_addr = (char*)shmat(shmid, NULL, 0);
    if (shm_addr == (char*)-1) {
        perror("shmat failed");
        return 1;
    }

    pid_t pid = fork();
    if (pid == -1) {
        perror("fork failed");
        return 1;
    }

    if (pid == 0) { // 子進(jìn)程:讀取共享內(nèi)存
        std::cout << "子進(jìn)程讀取共享內(nèi)存:" << shm_addr << std::endl;
        // 解除映射
        shmdt(shm_addr);
        return 0;
    } else { // 父進(jìn)程:寫入共享內(nèi)存
        strcpy(shm_addr, "Hello from parent via shared memory!");
        wait(NULL);
        // 解除映射并刪除共享內(nèi)存
        shmdt(shm_addr);
        shmctl(shmid, IPC_RMID, NULL);
        std::cout << "父進(jìn)程釋放共享內(nèi)存" << std::endl;
    }

    return 0;
}
  • 適用場景:大量數(shù)據(jù)的高頻交互(如實(shí)時(shí)數(shù)據(jù)傳輸、進(jìn)程間共享大數(shù)組/結(jié)構(gòu)體)。

補(bǔ)充:其他常見IPC機(jī)制

機(jī)制核心特點(diǎn)適用場景
消息隊(duì)列按類型/優(yōu)先級存儲(chǔ)消息,內(nèi)核管理,有容量限制進(jìn)程間異步、帶優(yōu)先級的消息傳輸
信號量用于進(jìn)程/線程同步,實(shí)現(xiàn)互斥/計(jì)數(shù)配合共享內(nèi)存解決競爭問題
套接字(Socket)支持跨網(wǎng)絡(luò)、跨主機(jī)通信,全雙工網(wǎng)絡(luò)進(jìn)程通信、本機(jī)跨進(jìn)程通信
信號(Signal)簡單的異步通知(如SIGUSR1/SIGUSR2)進(jìn)程間簡單事件通知(如退出)

二、fork(進(jìn)程)與thread(線程)的關(guān)系

fork()創(chuàng)建進(jìn)程和pthread創(chuàng)建線程是兩種完全不同的并發(fā)方式,但存在關(guān)聯(lián)和關(guān)鍵區(qū)別,核心總結(jié)如下:

1. 核心區(qū)別(最易混淆的點(diǎn))

維度fork(進(jìn)程)thread(線程)
內(nèi)存空間父子進(jìn)程私有地址空間(寫時(shí)復(fù)制)同一進(jìn)程的線程共享地址空間(代碼、數(shù)據(jù)、堆、文件描述符)
資源開銷高(復(fù)制頁表、文件描述符等)低(僅創(chuàng)建棧和寄存器上下文)
通信復(fù)雜度高(需IPC機(jī)制)低(直接讀寫共享變量,需加鎖)
調(diào)度單位進(jìn)程是OS調(diào)度的獨(dú)立單位線程是OS調(diào)度的最小單位(進(jìn)程是資源分配單位)
獨(dú)立性進(jìn)程崩潰不影響其他進(jìn)程線程崩潰會(huì)導(dǎo)致整個(gè)進(jìn)程退出
系統(tǒng)調(diào)用fork()、wait()、exit()pthread_create()、pthread_join()、pthread_exit()

2. fork與線程的關(guān)聯(lián)場景

(1)進(jìn)程內(nèi)有線程時(shí)調(diào)用fork的風(fēng)險(xiǎn)

若父進(jìn)程創(chuàng)建了多個(gè)線程后調(diào)用fork(),子進(jìn)程僅會(huì)復(fù)制調(diào)用fork的那個(gè)線程,其他線程會(huì)被終止,且可能導(dǎo)致:

  • 鎖狀態(tài)異常(子進(jìn)程繼承父進(jìn)程的鎖,但持有鎖的線程已消失,引發(fā)死鎖);
  • 資源未清理(如父進(jìn)程線程打開的文件、內(nèi)存)。
    → 解決方案:fork前通過pthread_atfork()注冊回調(diào)函數(shù),清理鎖/資源。
(2)fork與線程的選擇邏輯
  • fork():需進(jìn)程隔離(如子進(jìn)程崩潰不影響父進(jìn)程)、利用多CPU核心(進(jìn)程可被調(diào)度到不同核)、執(zhí)行獨(dú)立任務(wù)(如子進(jìn)程執(zhí)行execve替換程序);
  • 用線程:低開銷并發(fā)、高頻數(shù)據(jù)交互、共享資源多(如共享緩存/連接池)。
(3)混合使用場景

例如:父進(jìn)程創(chuàng)建線程處理網(wǎng)絡(luò)請求,同時(shí)fork子進(jìn)程處理耗時(shí)的磁盤IO(避免IO阻塞主線程),但需嚴(yán)格管理資源和同步。

3. 通俗類比

  • fork創(chuàng)建進(jìn)程:像復(fù)制一套完整的房子(有獨(dú)立的客廳、臥室、廚房),兩家人各自住,要傳遞東西需走大門(IPC);
  • 創(chuàng)建線程:像在同一套房子里多住幾個(gè)人,共享客廳/廚房(共享內(nèi)存),但拿同一碗飯時(shí)要排隊(duì)(加鎖)。

總結(jié)

  1. IPC機(jī)制核心:管道(匿名/命名)是基于文件描述符的單向字節(jié)流,適用于簡單通信;共享內(nèi)存是最快的IPC,直接共享物理內(nèi)存,但需同步機(jī)制;
  2. fork與線程的核心關(guān)系:兩者都是并發(fā)實(shí)現(xiàn)方式,fork創(chuàng)建獨(dú)立內(nèi)存空間的進(jìn)程(通信需IPC),線程共享進(jìn)程內(nèi)存(通信簡單但需同步),進(jìn)程內(nèi)有線程時(shí)fork需注意資源和鎖的問題。

一、線程間通信(Inter-thread Communication)詳解

線程間通信是同一進(jìn)程內(nèi)多個(gè)線程之間的數(shù)據(jù)交互或同步機(jī)制。由于線程共享進(jìn)程的地址空間(代碼段、數(shù)據(jù)段、堆、文件描述符等),通信方式比進(jìn)程間通信(IPC)更簡單,但需解決數(shù)據(jù)競爭問題。

1. 線程間通信的核心方式(按場景分類)

(1)共享內(nèi)存(最基礎(chǔ)、最常用)

線程天然共享進(jìn)程的內(nèi)存空間(全局變量、堆變量、靜態(tài)變量),這是線程通信的核心基礎(chǔ)。

  • 通信邏輯:一個(gè)線程修改共享變量,另一個(gè)線程讀取該變量,直接完成數(shù)據(jù)傳遞。
  • 核心問題:多線程同時(shí)讀寫共享變量會(huì)引發(fā)數(shù)據(jù)競爭(如計(jì)數(shù)器被多線程同時(shí)修改導(dǎo)致值錯(cuò)誤),需配合同步機(jī)制(互斥鎖、條件變量等)保證原子性。
  • 代碼示例(共享變量+互斥鎖)
#include <iostream>
#include <thread>
#include <mutex>

// 共享變量(線程間通信的載體)
int shared_data = 0;
// 互斥鎖:保護(hù)共享變量,避免數(shù)據(jù)競爭
std::mutex mtx;

// 線程1:修改共享變量
void write_data() {
    for (int i = 0; i < 5; ++i) {
        // 加鎖:保證臨界區(qū)(修改共享變量)原子執(zhí)行
        std::lock_guard<std::mutex> lock(mtx);
        shared_data++;
        std::cout << "寫線程:shared_data = " << shared_data << std::endl;
    }
}

// 線程2:讀取共享變量
void read_data() {
    for (int i = 0; i < 5; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        std::cout << "讀線程:shared_data = " << shared_data << std::endl;
    }
}

int main() {
    std::thread t1(write_data);
    std::thread t2(read_data);

    t1.join();
    t2.join();
    return 0;
}
  • 適用場景:高頻、少量數(shù)據(jù)交互(如狀態(tài)標(biāo)記、計(jì)數(shù)器、配置參數(shù))。

(2)條件變量(同步+通信,解決“等待-喚醒”場景)

條件變量用于線程間的同步通信,核心是“一個(gè)線程等待某個(gè)條件滿足,另一個(gè)線程滿足條件后喚醒它”,避免線程空等浪費(fèi)CPU資源。

  • 核心邏輯
    1. 等待線程:加鎖后檢查條件,不滿足則釋放鎖并阻塞,直到被喚醒;
    2. 喚醒線程:修改條件后,喚醒等待的線程,等待線程重新加鎖并檢查條件。
  • 代碼示例(生產(chǎn)者-消費(fèi)者模型)
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>

std::queue<int> msg_queue; // 共享隊(duì)列(通信載體)
std::mutex mtx;
std::condition_variable cv; // 條件變量

// 生產(chǎn)者線程:寫入數(shù)據(jù)
void producer() {
    for (int i = 1; i <= 3; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        msg_queue.push(i);
        std::cout << "生產(chǎn)者:寫入數(shù)據(jù) " << i << std::endl;
        cv.notify_one(); // 喚醒等待的消費(fèi)者
    }
}

// 消費(fèi)者線程:讀取數(shù)據(jù)
void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        // 等待條件:隊(duì)列非空(避免虛假喚醒,用while而非if)
        cv.wait(lock, []() { return !msg_queue.empty(); });
        
        int data = msg_queue.front();
        msg_queue.pop();
        std::cout << "消費(fèi)者:讀取數(shù)據(jù) " << data << std::endl;
        lock.unlock();
        
        if (data == 3) break; // 結(jié)束條件
    }
}

int main() {
    std::thread t_prod(producer);
    std::thread t_cons(consumer);

    t_prod.join();
    t_cons.join();
    return 0;
}
  • 適用場景:生產(chǎn)者-消費(fèi)者、任務(wù)隊(duì)列、等待某個(gè)事件觸發(fā)(如數(shù)據(jù)準(zhǔn)備完成)。

(3)信號量(計(jì)數(shù)型同步,兼顧通信)

信號量本質(zhì)是“計(jì)數(shù)器+鎖”,可用于線程間的同步,也能間接實(shí)現(xiàn)通信(如通過計(jì)數(shù)標(biāo)記數(shù)據(jù)是否就緒)。

  • 核心邏輯:信號量初始值為0(表示無數(shù)據(jù)),生產(chǎn)者生產(chǎn)數(shù)據(jù)后將信號量+1,消費(fèi)者獲取信號量(-1)后讀取數(shù)據(jù)。
  • 代碼示例(C++17+ semaphore)
#include <iostream>
#include <thread>
#include <semaphore>

std::counting_semaphore<1> sem(0); // 初始值0:無數(shù)據(jù)
int shared_data = 0;

void producer() {
    shared_data = 100;
    std::cout << "生產(chǎn)者:設(shè)置shared_data = " << shared_data << std::endl;
    sem.release(); // 信號量+1,通知消費(fèi)者
}

void consumer() {
    sem.acquire(); // 信號量-1,無數(shù)據(jù)則阻塞
    std::cout << "消費(fèi)者:讀取shared_data = " << shared_data << std::endl;
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);

    t1.join();
    t2.join();
    return 0;
}
  • 適用場景:限制并發(fā)數(shù)(如最多5個(gè)線程同時(shí)訪問資源)、簡單的“生產(chǎn)-消費(fèi)”同步。

(4)其他輔助方式

  • 線程本地存儲(chǔ)(TLS):看似“私有”,但可通過全局指針間接通信(如主線程給子線程的TLS賦值);
  • 回調(diào)函數(shù):線程執(zhí)行完任務(wù)后調(diào)用回調(diào)函數(shù),將結(jié)果傳遞給主線程;
  • 原子變量(std::atomic):無需加鎖的共享變量,適用于簡單數(shù)據(jù)(如bool、int)的通信(如std::atomic<bool> is_done = false;)。

2. 線程間通信的核心原則

  • 同步優(yōu)先:所有通信必須配合同步機(jī)制(鎖、條件變量、原子操作),避免數(shù)據(jù)競爭;
  • 最小臨界區(qū):鎖僅包裹必要的代碼,減少線程阻塞時(shí)間;
  • 避免死鎖:加鎖順序一致、及時(shí)釋放鎖、使用std::lock同時(shí)加多個(gè)鎖。

二、線程間通信 vs 進(jìn)程間通信(IPC):區(qū)別與聯(lián)系

1. 核心區(qū)別(表格對比)

維度線程間通信進(jìn)程間通信(IPC)
內(nèi)存基礎(chǔ)共享同一進(jìn)程地址空間(天然共享)進(jìn)程地址空間私有(需內(nèi)核/文件系統(tǒng)中介)
通信效率極高(直接讀寫內(nèi)存,無數(shù)據(jù)拷貝)較低(管道/消息隊(duì)列需內(nèi)核拷貝,共享內(nèi)存除外)
實(shí)現(xiàn)復(fù)雜度簡單(共享變量+同步機(jī)制)復(fù)雜(需調(diào)用專門的IPC系統(tǒng)調(diào)用,如pipe/shmget)
隔離性/安全性低(一個(gè)線程崩潰導(dǎo)致整個(gè)進(jìn)程退出)高(進(jìn)程崩潰不影響其他進(jìn)程)
同步機(jī)制互斥鎖、條件變量、原子變量、信號量信號量(System V/POSIX)、文件鎖
適用范圍同一進(jìn)程內(nèi)的線程任意進(jìn)程(有無親緣關(guān)系均可)
典型方式共享變量、條件變量、原子變量管道、共享內(nèi)存、消息隊(duì)列、套接字

2. 核心聯(lián)系

  • 共享內(nèi)存是共性:線程間通信的“共享變量”本質(zhì)是進(jìn)程內(nèi)的共享內(nèi)存;IPC的“共享內(nèi)存”是內(nèi)核級的共享內(nèi)存,本質(zhì)都是讓多個(gè)執(zhí)行單元訪問同一塊內(nèi)存;
  • 同步機(jī)制互通:信號量既可用于線程同步,也可用于進(jìn)程同步(System V信號量);互斥鎖也有“進(jìn)程間互斥鎖”(PTHREAD_PROCESS_SHARED屬性);
  • 場景互補(bǔ)
    • 若需低開銷、高頻交互,優(yōu)先用線程+線程間通信;
    • 若需隔離性、獨(dú)立崩潰域,優(yōu)先用進(jìn)程+IPC;
  • 混合使用:復(fù)雜系統(tǒng)中常同時(shí)存在“進(jìn)程+IPC”和“線程+線程通信”(如多進(jìn)程服務(wù)器,每個(gè)進(jìn)程內(nèi)有多個(gè)線程處理請求)。

3. 通俗類比

線程間通信進(jìn)程間通信(IPC)
同一間辦公室的同事交流:
直接說話(共享變量)、舉手示意(條件變量),無需出門
不同辦公室的同事交流:
發(fā)郵件(管道)、共享網(wǎng)盤(共享內(nèi)存)、打電話(套接字),需借助外部工具

三、實(shí)戰(zhàn)選型建議(新手必看)

  1. 選線程間通信
    • 場景:高頻數(shù)據(jù)交互(如實(shí)時(shí)計(jì)算、UI刷新)、資源共享多(如共享緩存、數(shù)據(jù)庫連接池)、低延遲要求;
    • 注意:必須做好同步,避免數(shù)據(jù)競爭和死鎖。
  2. 選IPC
    • 場景:進(jìn)程隔離(如子進(jìn)程執(zhí)行危險(xiǎn)操作)、跨進(jìn)程/跨主機(jī)通信(如客戶端-服務(wù)器)、避免單個(gè)進(jìn)程崩潰影響整體;
    • 注意:優(yōu)先選共享內(nèi)存(高效)或管道(簡單),套接字適用于跨網(wǎng)絡(luò)場景。

總結(jié)

  1. 線程間通信核心:依托進(jìn)程內(nèi)共享內(nèi)存,通過共享變量+同步機(jī)制(鎖、條件變量、原子變量)實(shí)現(xiàn),簡單高效但需解決數(shù)據(jù)競爭;
  2. 與IPC的核心區(qū)別:線程通信基于進(jìn)程內(nèi)共享內(nèi)存,IPC基于內(nèi)核/文件系統(tǒng)中介;線程通信效率高但隔離性低,IPC效率低但隔離性高;
  3. 核心聯(lián)系:共享內(nèi)存是兩者的共性基礎(chǔ),同步機(jī)制可互通,場景上互補(bǔ)。

到此這篇關(guān)于C++中fork()函數(shù)的文章就介紹到這了,更多相關(guān)C++ fork()內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • C語言中字母大小寫轉(zhuǎn)化簡單示例

    C語言中字母大小寫轉(zhuǎn)化簡單示例

    在C語言中,有時(shí)候我們遇到這樣的考題,將c語言大寫字母轉(zhuǎn)化為小寫字母,下面這篇文章主要給大家介紹了關(guān)于C語言中字母大小寫轉(zhuǎn)化的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • C語言測試n的階乘和x的n次方

    C語言測試n的階乘和x的n次方

    今天小編就為大家分享一篇關(guān)于C語言測試n的階乘和x的n次方,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • c++ 虛函數(shù)與純虛函數(shù)的區(qū)別(深入分析)

    c++ 虛函數(shù)與純虛函數(shù)的區(qū)別(深入分析)

    本篇文章是對c++中虛函數(shù)與純虛函數(shù)的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++中std::move移動(dòng)的實(shí)現(xiàn)

    C++中std::move移動(dòng)的實(shí)現(xiàn)

    std::move是C++11引入的關(guān)鍵特性,它通過將左值轉(zhuǎn)換為右值引用來觸發(fā)移動(dòng)語義,實(shí)現(xiàn)資源的高效轉(zhuǎn)移而非拷貝,本文解析了std::move的使用及典型應(yīng)用場景,感興趣的可以了解一下
    2026-01-01
  • C語言練習(xí)題:自由落體的小球簡單實(shí)例

    C語言練習(xí)題:自由落體的小球簡單實(shí)例

    下面小編就為大家?guī)硪黄狢語言練習(xí)題:自由落體的小球簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考,一起跟隨小編過來看看吧
    2016-05-05
  • C語言實(shí)現(xiàn)繪制立體餅圖的示例代碼

    C語言實(shí)現(xiàn)繪制立體餅圖的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何使用C語言實(shí)現(xiàn)繪制立體餅圖,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • C++實(shí)現(xiàn)簡單貪吃蛇游戲

    C++實(shí)現(xiàn)簡單貪吃蛇游戲

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡單貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • C\C++ 獲取當(dāng)前路徑實(shí)例詳解

    C\C++ 獲取當(dāng)前路徑實(shí)例詳解

    這篇文章主要介紹了C\C++ 獲取當(dāng)前路徑實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • 二叉搜索樹的插入與刪除(詳細(xì)解析)

    二叉搜索樹的插入與刪除(詳細(xì)解析)

    添加結(jié)點(diǎn)其實(shí)很容易,我們只需要找到結(jié)點(diǎn)所行對應(yīng)的位置就可以了,而且沒有要求是平衡的二叉搜索樹,因此每次添加結(jié)點(diǎn)都是在葉子結(jié)點(diǎn)上操作,不需要修改二叉搜索樹整體的結(jié)構(gòu)
    2013-09-09
  • C語言中自動(dòng)隱式轉(zhuǎn)換與類型強(qiáng)制轉(zhuǎn)換實(shí)例分析

    C語言中自動(dòng)隱式轉(zhuǎn)換與類型強(qiáng)制轉(zhuǎn)換實(shí)例分析

    這篇文章主要介紹了C語言中自動(dòng)隱式轉(zhuǎn)換與類型強(qiáng)制轉(zhuǎn)換實(shí)例分析,需要的朋友可以參考下
    2014-07-07

最新評論

张掖市| 喀喇沁旗| 临西县| 抚松县| 壤塘县| 红河县| 蓝山县| 略阳县| 陆良县| 新泰市| 抚松县| 通榆县| 高邑县| 邻水| 攀枝花市| 三穗县| 博乐市| 西昌市| 汉川市| 新昌县| 开化县| 综艺| 白河县| 渭南市| 治多县| 五莲县| 新安县| 乐安县| 股票| 监利县| 清水县| 商南县| 敖汉旗| 平阳县| 武穴市| 马尔康县| 嘉禾县| 科尔| 双峰县| 仁寿县| 包头市|