【C/C++】多線程開發:wait、sleep、yield全解析

文章目錄

  • 多線程開發:wait、sleep、yield全解析
    • 1 What
      • 簡要介紹
      • 詳細介紹
        • `wait()` — 條件等待(用于線程同步)
        • `sleep()` — 睡覺,定時掛起
        • `yield()` — 自愿讓出 CPU
    • 2 區別以及建議
      • 區別
      • 應用場景建議
    • 3 三者協作使用示例

多線程開發:wait、sleep、yield全解析

多線程開發中, wait()sleep()yield() 的正確使用對于控制線程行為、避免死鎖、提升性能至關重要。


1 What

簡要介紹

方法屬于哪類是否釋放鎖作用
wait()同步原語(條件變量)? 釋放鎖當前線程等待某個條件滿足,掛起執行。
sleep()時間控制? 不釋放鎖當前線程強制睡眠一段時間。
yield()調度建議? 不釋放鎖當前線程主動讓出 CPU,允許其他線程執行。

詳細介紹

wait() — 條件等待(用于線程同步)
  • std::condition_variable::wait()(C++11)
  • Java 的 Object.wait() 也類似

行為:

  • 線程在等待某個條件成立
  • 釋放所持的互斥鎖(mutex),進入阻塞狀態。
  • 條件滿足后,被 notify_one() / notify_all() 喚醒,重新競爭鎖并繼續執行。

C++ 示例:

std::mutex mtx;
std::condition_variable cv;
bool ready = false;void worker() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []{ return ready; }); // 釋放鎖等待條件成立std::cout << "Condition met, working..." << std::endl;
}

sleep() — 睡覺,定時掛起
  • std::this_thread::sleep_for()
  • std::this_thread::sleep_until()

行為:

  • 當前線程被強制阻塞指定時間
  • 不會釋放任何鎖
  • 時間一到,線程進入就緒狀態(可被調度)。

示例:

std::mutex mtx;void worker() {std::lock_guard<std::mutex> lock(mtx);std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "Wake up after 2 seconds.\n";
}

🔺 注意:如果你在持鎖狀態下調用 sleep(),會讓其它線程“餓死”或引發死鎖。


yield() — 自愿讓出 CPU
  • std::this_thread::yield()(C++11)
  • 實際為對操作系統 sched_yield() 的封裝

行為:

  • 當前線程主動放棄 CPU 時間片
  • 線程回到就緒隊列,允許其他同優先級線程執行。
  • 不會阻塞、不休眠、不釋放鎖。

示例:

void busy_wait() {while (!ready) {std::this_thread::yield(); // 避免 CPU 忙等}
}

2 區別以及建議

區別

特性wait()sleep()yield()
阻塞線程?? 是? 是? 否(可能暫停)
是否釋放鎖?? 是(必須配合 mutex 使用)? 否? 否
喚醒條件notify_one() / notify_all()時間到被 OS 再次調度
典型用途線程間同步,條件等待限制頻率、延時模擬忙等時避免 CPU 占用
所屬 APIcondition_variable / pthread_condstd::this_thread::sleep_for()std::this_thread::yield()

應用場景建議

場景推薦方法
等待某個狀態改變wait()
模擬延時 / 限速 / 輪詢間隔sleep()
忙等 / 自旋等待中降低 CPU 占用yield()

3 三者協作使用示例

驗證目標:

  • 主線程 sleep 控制節奏
  • 子線程 yield 等待任務
  • 條件變量 wait 同步工作

代碼目標:

  • 主線程每 1 秒產生一個任務。
  • 工作線程使用 yield() 自旋檢查是否有任務。
  • 一旦任務準備好,工作線程使用 wait() 等待條件變量通知,再執行任務。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <chrono>std::mutex mtx;
std::condition_variable cv;
std::atomic<bool> ready{false};
int task_counter = 0;// 工作線程:等待任務并執行
void worker_thread() {while (true) {// ? 自旋檢查任務是否準備好(減少 wait 的頻率)while (!ready.load()) {std::this_thread::yield(); // 主動讓出 CPU}std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return ready.load(); }); // 等待通知,并釋放鎖// 模擬任務處理std::cout << "[Worker] Executing task #" << task_counter << std::endl;ready = false;  // 標記任務完成if (task_counter >= 5) break;  // 結束條件}
}// 主線程:周期性產生任務
void task_producer() {for (int i = 1; i <= 5; ++i) {std::this_thread::sleep_for(std::chrono::seconds(1)); // 模擬任務生成延遲{std::lock_guard<std::mutex> lock(mtx);task_counter = i;ready = true;std::cout << "[Main] Task #" << i << " ready\n";}cv.notify_one(); // 通知工作線程}
}int main() {std::thread worker(worker_thread);std::thread producer(task_producer);producer.join();worker.join();std::cout << "All tasks finished.\n";return 0;
}

輸出:

[Main] Task #1 ready
[Worker] Executing task #1
[Main] Task #2 ready
[Worker] Executing task #2
[Main] Task #3 ready
[Worker] Executing task #3
[Main] Task #4 ready
[Worker] Executing task #4
[Main] Task #5 ready
[Worker] Executing task #5
All tasks finished.

代碼行為解析:

  • 主線程:

    • 每秒產生一個任務,調用 sleep_for()
    • 使用鎖保護 task_counterready 狀態。
    • 調用 cv.notify_one() 喚醒工作線程。
  • 工作線程:

    • 使用 yield() 忙等(在任務未準備好前避免 CPU 占用)。
    • 使用 condition_variable::wait() 掛起,等待任務準備。
    • 被通知后執行任務,打印日志,重置狀態。

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

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

相關文章

阿里云CDN刷新預熱--刷新URL

文章目錄 一、全英文URL刷新預熱二、摻雜中文的URL刷新預熱2.1 對帶中文URL進行編碼2.2 預熱刷新 三、CDN刷新-核心作用與價值3.1 核心作用3.2 核心價值3.3 典型使用場景 *最后我想說&#xff1a;請你不要相信我說的每一句話&#xff0c;這只是我的個人經驗* 一、全英文URL刷新…

Oracle 19c DG備庫報錯ORA-00313、ORA-00312、ORA-27037

Oracle 19c DG備庫報錯ORA-00313、ORA-00312、ORA-27037 錯誤排查問題處理錯誤排查 DG同步完成后,DG Broker show database發現以下告警信息: Database Warning(s):ORA-16826: apply service state is inconsistent with the DelayMins propertyORA-16789: standby redo log…

開源與閉源之爭:AI時代的創新博弈與未來抉擇

在人工智能技術狂飆突進的今天&#xff0c;開源與閉源之爭已不再局限于技術圈的討論&#xff0c;而是演變為一場關乎技術倫理、商業格局乃至人類文明走向的深度博弈。當Meta的Llama 3開源模型下載量突破百萬&#xff0c;當OpenAI的GPT-5繼續加固技術壁壘&#xff0c;這場沒有硝…

NIFI的處理器:JSLTTransformJSON 2.4.0

該處理器使用JSLT轉換FlowFile JSON有效負載的格式。使用轉換后的內容創建新的FlowFile&#xff0c;并將其路由到“成功”關系。如果JSLT轉換失敗&#xff0c;則將原始FlowFile路由到“失敗”關系。 需要注意的是&#xff0c;編譯JSLT轉換可能相當昂貴。理想情況下&#xff0c…

MySQL 索引失效及其解決辦法

一、前言 在數據庫優化中,索引(Index)是一項至關重要的技術手段,可以顯著提升查詢性能。然而,在實際開發過程中,MySQL 索引并不總是如預期生效。本文將從原理出發,系統地介紹索引失效的常見場景及其解決方案,幫助開發者有效規避性能陷阱。 二、索引基礎回顧 MySQL 支…

趨勢觸發策略

趨勢觸發策略(TS版)是一種基于TrendTriggerFactor(TTF)的交易策略,通過柱狀圖顏色變化指示市場趨勢的強度,并根據TTF的穿越信號進行買賣操作。 TTF是通過計算買方力量和賣方力量的差值除以兩者之和的一半再乘以100得到的。 當TTF大于100時,柱狀圖顯示為綠色,表示市場…

DeepSeek-R1 模型現已在亞馬遜云科技上推出

亞馬遜云科技提供眾多免費云產品&#xff0c;可以訪問&#xff1a;亞馬遜云科技 在剛剛過去的 Amazon re&#xff1a;Invent 期間&#xff0c;Amazon 首席執行官 Andy Jassy 分享了從 Amazon 自己在全公司開發近 1000 個生成式 AI 應用程序的經驗中汲取的寶貴經驗。從這種廣泛…

中臺項目-微前端qiankun-umimax

學習視頻&#x1f50a; 基礎&#xff1a; 黑馬前端基于qiankun搭建微前端項目實戰教程_嗶哩嗶哩_bilibili 路由、部署配置注意&#xff1a;qiankunvite微前端上線注意事項&#xff0c;base公共路徑設置_嗶哩嗶哩_bilibili 微前端 什么是微前端&#xff1f; 微前端是將前端應…

【Java學習筆記】代碼塊

代碼塊 介紹&#xff1a;代碼塊又稱為初始化塊&#xff0c;屬于類中的成員&#xff08;即是類的一部分&#xff09;&#xff0c;類似于方法&#xff0c;將邏輯語句封裝在方法體中&#xff0c;通過{}包圍起來 與類方法的不同點 無方法名 無返回類型 無參數 只有方法體&#…

spring boot 2.7集成舊的springfox-boot-starter swagger oas 3.0

舊版本目前已經不維護推薦使用 springdoc-openapi-ui&#xff0c;這里為了演示使用舊的最新依賴 <dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version> </dep…

Linux按鍵驅動測試方式詳細介紹

Linux按鍵驅動測試可采用以下分層方法&#xff1a; 基礎事件檢測 使用輸入子系統調試工具&#xff1a; sudo apt install evtest # 安裝事件測試工具 evtest # 選擇對應設備編號觸發按鍵后觀察終端輸出&#xff0c;正常情況應顯示&#xff1a; Event:…

USB學習【13】STM32+USB接收數據過程詳解

目錄 1.官方的描述2.HAL的流程把接收到的數據從PMA拷貝到用戶自己定義的空間中 3.處理接收到的數據4.最后再次開啟準備接收工作 1.官方的描述 2.HAL的流程 以上的官方說法我們暫時按下不表。 如果接收到數據&#xff0c;會激活中斷進入到USB_LP_CAN1_RX0_IRQHandler&#xff0…

上海內推 | 上海算法創新研究院-上海交大聯合招收空間智能/具身智能算法實習生

最近這一兩周不少公司已開啟春招和實習招聘。 不同以往的是&#xff0c;當前職場環境已不再是那個雙向奔赴時代了。求職者在變多&#xff0c;HC 在變少&#xff0c;崗位要求還更高了。 最近&#xff0c;我們又陸續整理了很多大廠的面試題&#xff0c;幫助一些球友解惑答疑&am…

C語言速成12之指針:程序如何在內存迷宮里找寶藏?

程序員Feri一名12年的程序員,做過開發帶過團隊創過業,擅長Java、鴻蒙、嵌入式、人工智能等開發,專注于程序員成長的那點兒事,希望在成長的路上有你相伴&#xff01;君志所向,一往無前&#xff01; 0. 前言&#xff1a;程序如何在內存迷宮里找寶藏&#xff1f; 想象內存是一個巨…

部署n8n

https://github.com/n8n-io/n8n docker volume create n8n_data docker run -it --rm --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n Discover 2192 Automation Workflows from the n8ns Community

ABP VNext + Orleans:Actor 模型下的分布式狀態管理最佳實踐

ABP VNext Orleans&#xff1a;Actor 模型下的分布式狀態管理最佳實踐 &#x1f680; &#x1f4da; 目錄 ABP VNext Orleans&#xff1a;Actor 模型下的分布式狀態管理最佳實踐 &#x1f680;一、引言&#xff1a;分布式系統的狀態挑戰 &#x1f4a1;二、架構圖與技術棧 &am…

構建安全AI風險識別大模型:CoT、訓練集與Agent vs. Fine-Tuning對比

構建安全AI風險識別大模型:CoT、訓練集與Agent vs. Fine-Tuning對比 安全AI風險識別大模型旨在通過自然語言處理(NLP)技術,檢測和分析潛在的安全威脅,如數據泄露、合規違規或惡意行為。本文從Chain-of-Thought (CoT)設計、訓練集構建、以及Agent-based方法與**AI直接調優…

Baklib內容中臺的主要構成是什么?

Baklib內容中臺核心架構 Baklib作為一站式知識管理平臺的核心載體&#xff0c;其架構設計圍繞智能搜索引擎優化技術與多終端適配響應系統展開。通過模塊化內容組件的靈活配置&#xff0c;企業可快速搭建知識庫、FAQ頁面及幫助中心等標準化場景&#xff0c;同時借助可視化數據看…

Ubuntu Desktop 24.04 常用軟件安裝步驟

文章目錄 Ubuntu Desktop 24.04 常用軟件安裝步驟Snipaste F1快捷截圖&#xff08;超方便 | 我6臺電腦每臺都用&#xff09;搜狗輸入法快速瀏覽工具 | 空格鍵快速預覽文件壁紙工具 | varietySSH 工具 | Termius 終端分屏工具 | TmuxCaffeine | 避免息屏小工具 一些設置將啟動臺…

詳細使用@rollup/plugin-inject的方式

rollup/plugin-inject 是一個 Rollup 插件&#xff0c;它允許你在構建時自動注入模塊中的變量引用&#xff0c;避免手動在每個文件中 import。Vite 使用的是 Rollup 構建底層&#xff0c;因此該插件在 Vite 項目中也適用。 一、使用場景 比如你希望在代碼中不手動寫 import { …