C++面試題,進程和線程方面(1)

文章目錄

  • 前言
  • 進程和線程有什么不同
  • 進程,線程的通訊方式
  • 什么是鎖
  • 為什么說鎖可以使線程安全
  • 加鎖有什么副作用
  • 總結


前言

這是個人總結進程和線程方面的面試題。如果有錯,歡迎佬們前來指導!!!


進程和線程有什么不同

進程是程序的動態執行的實例,每個進程都有獨立的地址空間,資源(如文件描述符,內存地址空間)和系統狀態。
獨立性:進程之間資源隔離,一個進程崩潰不會直接影響到其它進程
唯一標識:通過PID和PPID標識,形成樹狀結構(init為根進程)
動態性:生命周期包括創建(fork()),運行,阻塞,終止等狀態變化

線程是進程內的執行單元,共享進程的資源(如內存,文件描述符),但擁有獨立的棧和寄存器
輕量級:線程創建和切換的開銷遠小于進程
共享性:線程可直接訪問進程的全局變量,通信更高效,但也需要同步機制(如互斥鎖)來避免競爭
調度單位:線程是CPU調度的最小單位,進程是資源分配的最小單位

資源分配差異
進程是操作系統資源分配的基本單位,每個進程都有獨立的內存地址空間(代碼段,數據段,堆棧段),文件描述符等資源。這意味著每個進程在內存中都有自己的私有數據和執行環境,互補影響。
線程是進程內的執行流,共享同一進程的資源,包括內存空間,文件描述符等。多個線程可以訪問同一個進程的內存空間,因此線程之間的通信和數據共享更加方便
調度機制
進程是操作系統調度的基本單位,由操作系統進行調度管理。線程是CPU調度的基本單位,由內核調度器負責。
進程切換:需要切換虛擬地址空間,寄存器,文件描述符等,開銷大。
線程切換:僅需切換棧和寄存器,共享地址空間,開銷小。
創建與銷毀
創建進程需分配獨立內存,初始化PCB,調用fork()系統調用;銷毀進程需要回收全部資源,耗時較長。
創建線程僅需分配棧和線程控制塊,調用pthread_create()庫函數;銷毀線程僅釋放棧和線程控制塊,資源回收簡單。
通信機制對比
進程需通過IPC機制:管道,消息隊列,共享內存,信號量來實現進程間通信,同步需求低(資源獨立)。
線程直接通過共享內存(全局變量,堆)無需額外機制,同步需求高(需互斥鎖,條件變量等避免數據競爭)。

在這里插入圖片描述


進程,線程的通訊方式

進程間通信方式

  1. 管道(pipe)
    匿名管道:基于內存的FIFO隊列,僅限于父子進程或兄弟進程間單向通信。通過pipe()系統調用創建,讀寫端由不同進程分別關閉
    命名管道:通過文件系統路徑標識,允許無親緣關系的進程通信。使用mkfifo()創建,支持雙向通信但需自行管理同步
    特定:簡單高效,但容量有限且僅支持半雙工,適合簡單數據流傳輸
  2. 消息隊列(message queue)
    結構:內核維護的鏈表結構,消息按FIFO或優先級排序存儲,支持多進程異步讀寫。
    使用場景:適合需要解耦生產者和消費者的場景(如任務分布系統),支持支持化消息和確認機制,但需處理消息丟失或重復問題
    如System V的msgget/msgsnd/msgrcv或POSIX的mq_open/mq_send/mq_receive
  3. 共享內存(shared memory)
    原理:多個進程映射同一個物理內存區域,直接讀寫數據。
    同步機制:
    信號量:通過PV操作控制訪問權限,如System V的semp或POSIX信號量
    互斥鎖/條件變量:在共享內存中嵌入鎖結構,配合線程同步
    優勢:速度最快,適合大數據量高頻通信(如視頻處理);缺點是需要顯示同步,編程復雜度高。
  4. 信號(signal)
    用途:異步通知進程特定事件(如SIGKILL終止進程)。通過kill()或signal()發送和處理
    局限性:信號編號少,不適合復雜數據傳遞,多用于進程控制
  5. 套接字(socket)
    跨進程特性:支持本地和網絡通信。通過socket()/bind()/listen()/accept()建立連接,實現全雙工通信
    應用場景:分布式系統,C/S架構,需要處理序列化和協議設計
  6. 信號量(semaphores)
    功能:計數器機制協調資源訪問,解決互斥與同步問題。分為System V信號量集和POSIX信號量
    如初始化信號量為1(互斥鎖),進程訪問共享資源前執行sem_wait(),是否后執行sem_post()。

線程共享進程資源,通信更側重同步而非數據傳輸

  1. 共享變量與鎖機制
    互斥鎖(Mutex):確保臨界區原子性。使用pthread_mutex_init()初始化,lock()/unlock()包含資源
    讀寫鎖(Read-Write-Lock):允許多讀單寫,提高并發性。通過pthread_rwlock實現,適用于讀多寫少場景
  2. 條件變量(Condition Variable)
    協作機制:線程等待特定條件成立(如資源就緒)。需與互斥鎖配合,使用pthread_cond_wait()掛其線程,pthread_cond_signal()喚醒
  3. 信號量(Semaphores)
    線程級同步:與進程間信號類似,但作用域限于同一進程。POSIX無名信號量通過sem_init()初始化。

信號量的互斥與同步作用
使用信號量實現進程間的互斥與同步主要通過以下步驟:

  1. 初始化信號量:創建一個信號量并初始化其值。對于互斥訪問,信號量通常初始化為1。列如,使用sem_init函數初始化信號量,或使用sem_open創建命名信號量并初始化
  2. 進入臨界區前執行P操作:進程在進入臨界區前執行P操作(等待操作),即sem_wait或semop函數。如果信號量大于0,則將其減1并允許進程進入臨界區;如果信號量值為0,則進程被阻塞,直到信號量值大于0
  3. 退出臨界區后執行V操作:進程在提出臨界區后執行V操作(信號操作),即sem_post或semp函數。這將信號量加1,并喚醒一個等待該信號量的進程
  4. 銷毀信號量:在不再需要信號量時,使用sem_destory或sem_unlink函數銷毀信號量,釋放相關資源
    通過上訴步驟,信號量可以確保多個進程對共享資源的互斥訪問,避免數據競爭和不一致。

在這里插入圖片描述


什么是鎖

鎖是一種用于同步并發訪問共享資源的機制,通過限制對共享資源的訪問順序,確保在任意時刻只有一個線程能進入臨界區。其本質是內存中的一個整形變量,通過狀態(如0表示空閑,1表示鎖定)實現資源占用的原子控制。在多線程環境下,鎖的作用包括:
1. 互斥訪問:防止多個線程同時修改空閑數據,導致不可預測的結果
2. 數據一致性:確保線程操作空閑資源時的中間狀態對其它線程不可見
3. 執行順序控制:通過信號量等機制協調線程的執行流程

在linux系統中,常見的鎖類型包括互斥鎖(mutex),讀寫鎖(rwlock),自旋鎖(spinlock),信號量(semaphore)。

  1. 互斥鎖(Mutex)
    定義:互斥鎖是最基本且最常用的鎖類型,用于保護共享資源,確保在任何時候只有一個線程或進程可以訪問該資源
    實現:通過pthread_mutex_t類型實現,可以通過靜態或動態方式創建。靜態創建使用PTHREAD_MUTEX_INITALIZER,動態創建使用pthread_mutex_init函數。
    操作:主要操作包括pthread_mutex_lock(獲取鎖),pthread_mutex_unlock(釋放鎖)和pthread_mutex_destroy(銷毀鎖)

  2. 讀寫鎖(RWLock)
    定義:讀寫鎖允許多個線程同時讀取共享資源,但只允許一個線程寫入資源。這樣在讀操作頻繁而寫操作較少的場景下可以顯著提高并發性能
    實現:通過pthread_rwlock_t類型實現,可以通過靜態或動態方式創建。靜態創建使用PTHREAD_RWLOCK_INITALIZER,動態創建使用pthread_rwlock_init函數。
    操作:主頁操作包括pthread_rwlock_rdlock(獲取讀鎖),pthread_rwlock_wrlock(獲取寫鎖),pthread_rwlock_unlock(釋放鎖)和pthread_rwlock_destroy(銷毀鎖)

  3. 信號量(Semaphore):
    定義:信號量用于控制多個進程或線程對共享資源的訪問,實現更復雜的同步需求
    實現:通過sem_t類型實現,可以通過靜態或動態方式創建。靜態創建使用SEM_FAILED,動態創建使用sem_init函數
    操作:主要操作包括sem_wait(獲取信號量),sem_post(釋放信號量)和sem_destroy(銷毀信號量)

在這里插入圖片描述


為什么說鎖可以使線程安全

線程安全是指在多線程環境下,多個線程同時訪問共享資源時,能夠正確的處理共享數據,保證數據的一致性和正確性,而不會導致不確定的結果或產生競態條件。具體來說,線程安全的代碼在多線程并發執行時,能夠按照預期正確運行,不會因為共享資源的并發訪問而引發錯誤。
線程安全的特點:
1.原子性:對共享資源的操作是原子的,要么完全執行,要么不執行,不能被中斷或分割
2.可見性:一個線程對共享變量的修改,其他線程能夠立即看到
3.有序性:程序執行的順序按照代碼的先后順序進行,避免指令重排序導致的問題
常見的線程安全問題
1.競態條件:多個線程同時修改同一變量,導致結果不確定
2.死鎖:兩個或多個線程在執行過程中,因爭奪資源而造成的一種僵局
3.活鎖:兩個或多個線程在執行過程中,因爭奪資源而不斷重復嘗試,但都無法取的進展
4.饑餓:某個線程無法獲得必要的資源或條件,導致無法繼續執行

鎖通過以下機制解決多線程并發問題:
1. 強制互斥訪問臨界區:
鎖確保同一時間僅有一個線程進入臨界區,其它線程需等待鎖釋放。解決了原子性問題,避免多個線程同時修改共享資源(互斥鎖通過原子操作和等待隊列,確保臨界區代碼串行執行)
2. 內存屏障(?):
鎖的獲取和釋放操作隱含內存屏障,強制刷新緩存并阻止指令重排,從而保證可見性和有序性
3. 防止競態條件:
競態條件源于多個線程對共享資源的非協調訪問。鎖通過強制同步,將并發操作轉換為順序執行,消除執行順序的不確定性(若兩個線程同時執行a++,未加鎖可能因非原子操作導致結果錯誤;加鎖后,操作變為原子的,結果正確)


加鎖有什么副作用

性能開銷:
鎖的獲取和釋放操作本身需要消耗系統資源,可能成為程序性能瓶頸

  1. 原子操作與上下切換
    原子指令開銷:鎖的底層依賴CPU的原子指令(如xchg, cmpxchg),這些指令會觸發總線鎖定或緩存同步,導致CPU流水線暫停,降低指令級并行性
    上下文切換:互斥鎖(Mutex)在鎖競爭時會讓線程進入睡眠狀態(通過futex系統調用),觸發線程調度和上下文切換。若鎖競爭激烈,頻繁的切換會顯著增加CPU開銷
  2. 自旋鎖的CPU浪費:
    自旋鎖(Spinlock)通過忙等待(Busy Waiting)獲取鎖,若鎖持有時間較長,會持續占用CPU核心,浪費計算資源(單核CPU陷阱:在單核系統中,自旋鎖可能導致死鎖)
  3. 緩存失效:
    多個線程競爭同一鎖時,鎖變量的緩存行會在不同CPU核心之間頻繁無效化,導致緩存一致性協議的額外開銷

死鎖
不合理的鎖使用可能導致死鎖,即多個線程互相等待對方釋放鎖,程序永久阻塞。死鎖的四個必要條件:
1. 互斥訪問:鎖本身是獨占資源
2. 持有并等待:線程持有鎖的同時請求其它鎖
3. 不可剝奪:鎖只能由持有者釋放
4. 循環等待:線程間形成環形等待鏈

活鎖
活鎖是死鎖的一種變體:線程不斷嘗試獲取鎖失敗,但未進入阻塞狀態,導致CPU資源浪費(兩個線程同時檢測到對方持有鎖,主動釋放自己的鎖并重試,形成無限循環)

其它副作用:
1. 資源泄漏:忘記釋放鎖導致其它線程永久阻塞
2. 錯誤處理復雜性:臨界區內的代碼若拋出異常或提取返回,需確保鎖被釋放(可通過RAII模式解決,如C++的std::lock_guard)
3. 鎖與信號的交互:信號處理函數中不可使用非異步信號安全函數,否則可能引發死鎖


總結

以上就是我總結的C++面試題,進程和線程方面(1)

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/70372.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/70372.shtml
英文地址,請注明出處:http://en.pswp.cn/web/70372.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

視頻mp4垂直拼接 水平拼接

視頻mp4垂直拼接 水平拼接 pinjie_v.py import imageio import numpy as np import os import cv2def pinjie_v(dir1,dir2,out_dir):os.makedirs(out_dir, exist_okTrue)# 獲取目錄下的所有視頻文件video_files_1 [f for f in os.listdir(dir1) if f.endswith(.mp4)]video_fi…

Unity攝像機與燈光相關知識

一、Inspector窗口 Inspector窗口可以查看和編輯對象的屬性以及設置 其中包含各種組件,例如用Cube對象來舉例 1.Sphere(Mesh)組件: 用來決定對象的網格屬性,例如球體網格為Sphere、立方體網格為Cube 2.Mesh Renderer組件: 用來設置…

C++(17):為optional類型構造對象

C++(17):optional,多了一個合理的選擇_c++17 max-CSDN博客 介紹了optional做為函數返回值的一種方式 其實optional也可以作為對象來使用 #include &

探索關鍵領域的AI工具:機器學習、深度學習、計算機視覺與自然語言處理

引言 在人工智能(AI)迅猛發展的今天,機器學習(ML)、深度學習(DL)、計算機視覺(CV)和自然語言處理(NLP)已經成為解決復雜問題的關鍵技術。無論是自動駕駛車輛的視覺識別,還是智能助手的對話理解,這些技術都在改變著世界。本文將介紹在各個領域…

基于vue和微信小程序的校園自助打印系統(springboot論文源碼調試講解)

第3章 系統設計 3.1系統功能結構設計 本系統的結構分為管理員和用戶、店長。本系統的功能結構圖如下圖3.1所示: 圖3.1系統功能結構圖 3.2數據庫設計 本系統為小程序類的預約平臺,所以對信息的安全和穩定要求非常高。為了解決本問題,采用前端…

Windows 快速搭建C++開發環境,安裝C++、CMake、QT、Visual Studio、Setup Factory

安裝C 簡介 Windows 版的 GCC 有三個選擇: CygwinMinGWmingw-w64 Cygwin、MinGW 和 mingw-w64 都是在 Windows 操作系統上運行的工具集,用于在 Windows 環境下進行開發和編譯。 Cygwin 是一個在 Windows 上運行的開源項目,旨在提供類Uni…

MKS SERVO42E57E 閉環步進電機_系列10 STM32_脈沖和串口例程

文章目錄 第1部分 產品介紹第2部分 相關資料下載2.1 MKS E系列閉環步進驅動資料2.2 源代碼下載2.3 上位機下載 第3部分 脈沖控制電機運行示例第4部分 讀取參數示例4.1 讀取電機實時位置4.2 讀取電機實時轉速4.3 讀取電機輸入脈沖數4.4 讀取電機位置誤差4.5 讀取電機IO端口狀態 …

【宏基因組】MaAsLin2

教學手冊:學習手冊 MaAsLin2 # BiocManager::install("Maaslin2",force TRUE)library(Maaslin2) # 用的是相對豐度,行名為-ID行樣本,列為細菌 input_data system.file("extdata", "HMP2_taxonomy.tsv", package"…

【消息隊列】認識項目

1. 項目介紹 該項目是去實現一個簡單的消息隊列,包含服務器,客戶端的實現,客戶端通過遠程方法調用與服務器進行交互。采用自定義應用層協議,下層使用 TCP 協議進行數據在網絡中傳輸,核心功能提供了虛擬主機&#xff0…

vue從入門到精通(十一):條件渲染

條件渲染 1.v-if 寫法: (1).v-if“表達式” (2).v-else-if“表達式” (3).v-else“表達式” 適用于:切換頻率較低的場景。 特點:不展示的DOM元素直接被移除。 注意:v-if可以和:v-else-if、v-else一起使用,但要求結構不能被“打斷” 2.v-show 寫法:v-show“…

Python爬蟲基礎文件操作

文件操作 引言 爬蟲爬取的一切內容都是在內存進行的,這樣會有什么問題嗎?如果一旦短電或著發生意外電腦關機了那么你的工作成果將瞬間消失。所以,我們還缺少數據在本地文件系統進行持久化的能力,簡單的來說就是文件讀寫操作。文…

OpenCV中的邊緣檢測

邊緣檢測是圖像處理和計算機視覺中的關鍵技術之一,旨在識別圖像中像素強度發生顯著變化的區域,這些區域通常對應于物體的邊界或輪廓。邊緣檢測在機器視覺中具有重要的需求背景,主要體現在以下幾個方面: 圖像分割:邊緣…

【簡歷優化】性能調優 — 編程性能調優篇

😊你好,我是小航,一個正在變禿、變強的文藝傾年。 🔔本文講解【簡歷優化】性能調優 — 編程性能調優篇,期待與你一同探索、學習、進步,一起卷起來叭! 目錄 一、編程性能調優字符串String 發展優…

深入理解 MySQL 8 C++ 源碼:SELECT MOD(MONTH(NOW()), 2) 的函數執行過程

MySQL 作為最流行的關系型數據庫之一,其內部實現機制一直是開發者探索的熱點。本文將以一條簡單的 SQL 查詢 SELECT MOD(MONTH(NOW()), 2) 為例,深入分析 MySQL 8 源碼中內置函數 MOD、MONTH 和 NOW 的執行過程,揭示其底層實現邏輯。 一、SQL…

RNN中遠距離時間步梯度消失問題及解決辦法

RNN中遠距離時間步梯度消失問題及解決辦法 RNN 遠距離時間步梯度消失問題LSTM如何解決遠距離時間步梯度消失問題 RNN 遠距離時間步梯度消失問題 經典的RNN結構如下圖所示: 假設我們的時間序列只有三段, S 0 S_{0} S0? 為給定值,神經元沒有…

Tomcat理論(Ⅰ)

目錄 服務器流程圖一覽 一、JavaWeb前奏(了解) 1. C/S結構 2. B/S結構 3. 靜態網頁&動態網頁 4.常見的網頁 5.Web服務器 知名服務器: ?編輯 二、Tomcat安裝(熟練) 1.Tomcat概述 2.Tomcat的作用 3.Tomcat安裝 4.Tomcat測試 3.…

如何使用 DeepSeek R1 構建開源 ChatGPT Operator 替代方案

開源大型語言模型(LLMs)的興起使得創建 AI 驅動的工具比以往任何時候都更容易,這些工具可以與 OpenAI 的 ChatGPT Operator 等專有解決方案相媲美。在這些開源模型中,DeepSeek R1 以其強大的推理能力、自由的可訪問性和適應性而脫…

使用Docker Desktop部署GitLab

1. 環境準備 確保Windows 10/11系統支持虛擬化技術(需在BIOS中開啟Intel VT-x/AMD-V)內存建議≥8GB,存儲空間≥100GB 2. 安裝Docker Desktop 訪問Docker官網下載安裝包安裝時勾選"Use WSL 2 instead of Hyper-V"(推薦…

【復習】Java集合

集合概念 集合與數組 數組是固定長度;集合是動態長度的數據結構,需要動態增加或刪除元素 數組可以包含基本數據類型和對象;集合只能包含對象 數組可以直接訪問元素;集合需要通過迭代器訪問元素 線程安全的集合? …

vue3 文件類型傳Form Data數據格式給后端

在 Vue 3 中,如果你想將文件(例如上傳的 Excel 文件)以 FormData 格式發送到后端,可以通過以下步驟實現。這種方式通常用于處理文件上傳,因為它可以將文件和其他數據一起發送到服務器。 首先,創建一個 Vue…