c++多線程(3)------休眠函數sleep_for和sleep_until

  • 操作系統:ubuntu22.04
  • IDE:Visual Studio Code
  • 編程語言:C++11

算法描述

這兩個函數都定義在 頭文件中,屬于 std::this_thread 命名空間,用于讓當前線程暫停執行一段時間。

函數功能
sleep_for(rel_time)讓當前線程休眠一段相對時間(例如:休眠 100 毫秒)
sleep_until(abs_time)讓當前線程休眠到某個絕對時間點(例如:休眠到 2025年9月15日中午12:00)

函數原型

#include <thread>
#include <chrono>// 1. 休眠一段相對時間
template <class Rep, class Period>
void std::this_thread::sleep_for(const std::chrono::duration<Rep, Period>& rel_time);// 2. 休眠到某個絕對時間點
template <class Clock, class Duration>
void std::this_thread::sleep_until(const std::chrono::time_point<Clock, Duration>& abs_time);

?? 注意:如果傳入負的 rel_time,sleep_for 的行為等同于不休眠(立即返回)。

sleep_for 詳解:休眠一段相對時間

? 語法示例:

using namespace std::chrono;// 休眠 100 毫秒
std::this_thread::sleep_for(100ms);// 或者寫成:
std::this_thread::sleep_for(milliseconds(100));
std::this_thread::sleep_for(seconds(1));        // 休眠 1 秒
std::this_thread::sleep_for(microseconds(500)); // 500 微秒

🧠 工作原理:

  • 當前線程調用 sleep_for 后,會進入阻塞狀態(blocked)。
  • 操作系統將其從 CPU 調度隊列中移除。
  • 經過指定時間后,操作系統將線程重新放入就緒隊列,等待調度執行。
  • 線程恢復執行。

?? 注意事項:

  • 實際休眠時間 ≥ 指定時間
    因為操作系統調度不是實時的,sleep_for 只保證“至少休眠這么長時間”,但可能更長(尤其在系統負載高時)。

  • 精度取決于系統和時鐘
    通常系統時鐘精度為 1~15 毫秒,所以 sleep_for(1us) 可能實際休眠 1ms。

  • 可被中斷嗎?
    在標準 C++ 中,不能被信號或外部事件中斷(不像 POSIX 的 sleep())。一旦調用,必須等到時間結束。

使用場景
場景1:控制循環頻率(如游戲主循環、傳感器采樣)

while (running) 
{read_sensor();process_data();std::this_thread::sleep_for(10ms); // 控制每 10ms 執行一次
}

場景2:重試機制中的退避策略(Retry with Backoff)

for (int i = 0; i < 3; ++i) 
{if (try_connect()) break;std::this_thread::sleep_for(std::chrono::milliseconds(100 * (i + 1))); // 遞增等待
}

sleep_until 詳解:休眠到某個絕對時間點

? 語法示例:

using namespace std::chrono;// 獲取當前時間 + 2 秒
auto now = system_clock::now();
auto two_seconds_later = now + seconds(2);
std::this_thread::sleep_until(two_seconds_later);// 或者指定一個具體時間點(比如明天上午 9:00)
auto tomorrow = system_clock::now() + hours(24);
auto nine_am = std::chrono::time_point_cast<hours>(tomorrow);
nine_am += hours(9); // 假設今天是 0 點,加 9 小時
std::this_thread::sleep_until(nine_am);

🧠 工作原理:

  • sleep_until 接收一個 time_point 類型的時間點。
  • 線程會一直阻塞,直到系統時鐘達到或超過該時間點。
  • 如果當前時間已經晚于或等于目標時間點,則 sleep_until 立即返回,不休眠。

? 使用場景
場景1:定時任務(如每天凌晨執行)

void run_daily_task_at_midnight() 
{while (true) {auto now = system_clock::now();auto tomorrow = system_clock::from_time_t(std::chrono::system_clock::to_time_t(now) + 86400); // 明天 00:00:00auto midnight = std::chrono::time_point_cast<seconds>(tomorrow);std::this_thread::sleep_until(midnight);perform_daily_backup();}
}

場景2:多個線程同步到同一時間點啟動

auto start_time = std::chrono::system_clock::now() + std::chrono::seconds(5);// 所有線程都調用:
std::this_thread::sleep_until(start_time);
// 從而實現“5秒后同時開始”

💡 這比每個線程自己計算 sleep_for(5s) 更精確,避免了啟動延遲累積誤差。

sleep_for vs sleep_until 對比

特性sleep_forsleep_until
時間類型duration(持續時間)time_point(時間點)
語義“我要睡 5 秒”“我要睡到明天 9:00”
是否受系統時間調整影響是(如果系統時間被修改)
適合場景延遲、重試、節流定時任務、時間同步
若目標時間已過休眠指定時間立即返回(不休眠)

?? 注意:sleep_until 使用的是 system_clock,如果用戶手動調整了系統時間,可能導致線程提前喚醒或延遲喚醒。

如果需要更穩定的時鐘,可使用 steady_clock(見下文)。

推薦使用 steady_clock 避免系統時間跳變

雖然 system_clock 是最常用的時鐘,但它受系統時間調整(如 NTP 同步、手動修改)影響。

對于延遲控制類任務,建議使用 steady_clock,它是單調遞增的,不會倒退。
示例:使用 steady_clock 的 sleep_until

auto start = std::chrono::steady_clock::now();
auto deadline = start + std::chrono::milliseconds(100);std::this_thread::sleep_until(deadline); // 推薦用于定時延遲
steady_clock 不受系統時間修改影響,更適合做超時、延遲等操作。

常見誤區與注意事項

? 誤區1:sleep_for(1ms) 一定能精確休眠 1ms

→ 錯!受操作系統調度精度限制,實際可能休眠 1~15ms。
? 誤區2:sleep_until 絕對可靠

→ 如果系統時間被手動調整或 NTP 校正,system_clock 時間點可能跳變,導致提前或延遲喚醒。
? 誤區3:可以在任意線程調用

→ 可以,但注意:主線程調用也會阻塞整個程序。
? 最佳實踐:

延遲控制 → 優先用 sleep_for + steady_clock
定時任務 → 用 sleep_until + system_clock
高精度需求 → 考慮使用平臺特定 API(如 nanosleep on Linux)

完整示例代碼

#include <iostream>
#include <thread>
#include <chrono>int main()
{using namespace std::chrono;std::cout << "Start: " << system_clock::now().time_since_epoch().count() << std::endl;// 1. sleep_for:休眠 2 秒std::cout << "Sleeping for 2s..." << std::endl;std::this_thread::sleep_for(seconds(2));// 2. sleep_until:休眠到 3 秒后auto target = steady_clock::now() + milliseconds(1500);std::cout << "Sleeping until steady time point..." << std::endl;std::this_thread::sleep_until(target);std::cout << "Done!" << std::endl;return 0;
}

總結

函數用途推薦時鐘注意事項
sleep_for(duration)休眠一段相對時間steady_clock保證最小休眠時間
sleep_until(time_point)休眠到某個絕對時間system_clock受系統時間調整影響

? 一句話總結:

用 sleep_for 控制“延遲多久”,
用 sleep_until 控制“什么時候開始”。

它們是多線程中實現節流、重試、定時、同步啟動等行為的基礎工具,理解其差異和適用場景,能讓你寫出更健壯的并發程序。

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

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

相關文章

Intel RealSense D455深度相機驅動安裝與運行

Intel RealSense D455深度相機安裝過程遇到過一些報錯&#xff0c;所以記錄一下安裝過程&#xff01;&#xff01;&#xff01;以后方便回顧。 1.安裝最新的IntelRealSense SDK2.0 (1) 注冊服務器的公鑰 sudo apt-get update && sudo apt-get upgrade && su…

從異步到半同步:全面解讀MySQL復制的數據一致性保障方案

MySQL 主從復制&#xff08;Replication&#xff09;是其最核心的高可用性和擴展性功能之一。它的原理是將一個 MySQL 實例&#xff08;稱為主庫 Master&#xff09;的數據變更&#xff0c;自動同步到另一個或多個 MySQL 實例&#xff08;稱為從庫 Slave&#xff09;的過程。下…

PostgreSQL GIN 索引揭秘

文章目錄什么是GIN Index?示例場景GIN Index的原理GIN Index結構MetapageEntriesLeaf PagesEntry page 和 Leaf page 的關系Posting list 和posting tree待處理列表&#xff08;Pending List&#xff09;進階解讀GIN index索引結構總結什么是GIN Index? GIN (Generalized In…

開源多模態OpenFlamingo橫空出世,基于Flamingo架構實現圖像文本自由對話,重塑人機交互未來

注&#xff1a;此文章內容均節選自充電了么創始人&#xff0c;CEO兼CTO陳敬雷老師的新書《GPT多模態大模型與AI Agent智能體》&#xff08;跟我一起學人工智能&#xff09;【陳敬雷編著】【清華大學出版社】 清華《GPT多模態大模型與AI Agent智能體》書籍配套視頻課程【陳敬雷…

電子衍射模擬:基于GPU加速的MATLAB/Julia實現

點擊 “AladdinEdu&#xff0c;同學們用得起的【H卡】算力平臺”&#xff0c;注冊即送-H卡級別算力&#xff0c;80G大顯存&#xff0c;按量計費&#xff0c;靈活彈性&#xff0c;頂級配置&#xff0c;學生更享專屬優惠。 引言&#xff1a;電子衍射模擬的重要性與計算挑戰 電子…

easyExcel動態應用案例

代碼鏈接&#xff1a;https://download.csdn.net/download/ly1h1/919402991.案例說明&#xff1a;1.1.導入功能導入數據實現轉換成 List<List<String>> headers和 List<List<String>> datas&#xff0c;后續補充可以與數據模型注解結合&#xff0c;形…

【數據結構入門】排序算法(5):計數排序

目錄 1. 比較排序和非比較排序 2. 計數排序的原理 2.1 計數排序的弊端 3.代碼復現 3.1 代碼分析 3.2 排序核心 3.3 時間、空間復雜度 1. 比較排序和非比較排序 比較排序是根據排序元素的具體數值比較來進行排序&#xff1b;非比較排序則相反&#xff0c;非比較排序例如&…

輸入3.8V~32V 輸出2A 的DCDC降壓芯片SCT9320

同志們&#xff0c;今天來個降壓芯片SCT9320。輸入3.8V~32V&#xff0c;輸出最高可以達到2A。0.8V的參考電壓。500k的開關頻率。一共八個引腳&#xff0c;兩個NC&#xff08;為什么不做成六個引腳呢&#xff1f;&#xff09;。EN引腳懸空或者接到VIN都可以直接啟動&#xff0c;…

C++類和對象詳解(2);初識類的默認成員函數

1.類的默認成員函數默認成員函數就是用戶沒有顯示實現&#xff0c;編譯器會自動生成的成員函數稱為默認成員函數。一個類我們不寫的情況下編譯器會默認生成以下的6個默認成員函數。&#xff08;1&#xff09;構造函數&#xff1a;主要完成初始化的工作&#xff08;2&#xff09…

PLC通信 Tpc客戶端Socket

1.PLC通信 namespace _2.PLC通信 {public partial class Form1 : Form{public Form1(){InitializeComponent();}//連接//1.型號: 跟PLC溝通 使用哪個型號的PLC//2.IP 同上//3.機臺號:同上//4.插槽號:同上Plc plc new Plc(CpuType.S71200, "192.168.25.80", 0, 1);pr…

Android 開發實戰:從零到一集成 espeak-ng 實現中文離線 TTS(無需賬號開箱即用)

簡介 在移動應用開發中,語音合成(TTS)技術是提升用戶體驗的重要工具。然而,許多開發者在集成 TTS 時面臨依賴網絡、需注冊賬號、功能受限等問題。本文將帶你從零開始,通過開源項目 espeak-ng,實現無需賬號、開箱即用的中文離線語音播報。 文章將覆蓋以下核心內容: esp…

直播APP集成美顏SDK詳解:智能美妝功能的開發實戰

在這個“顏值即正義”的時代&#xff0c;用戶對直播APP的第一印象&#xff0c;往往來自主播的畫面質量。高清的視頻固然重要&#xff0c;但如果缺少自然美顏和智能美妝功能&#xff0c;觀眾體驗就會大打折扣。于是&#xff0c;美顏SDK成了直播行業的“標配”。今天&#xff0c;…

C++內存管理:new與delete的深層解析

1. 引言在C的世界里&#xff0c;動態內存管理是一個核心話題。對于從C語言過渡到C的開發者來說&#xff0c;一個常見的困惑是&#xff1a;既然C語言的malloc和free依然可以在C中使用&#xff0c;為什么C還要引入new和delete這兩個操作符&#xff1f;本文將深入探討這兩對內存管…

【AI開發】【前后端全棧】[特殊字符] AI 時代的快速開發思維

&#x1f680; AI 時代的快速開發思維 —— 以 Django Vue3 為例的前后端分離快捷開發流程 一、AI 時代的開發新思路 在 AI 的加持下&#xff0c;軟件開發不再是“純體力活”&#xff0c;而是 思維工具自動化 的協作。 過去&#xff1a;需求 → 設計 → 開發 → 測試 → 上…

Day24_【深度學習(3)—PyTorch使用—張量的創建和類型轉換】

一、創建張量1.張量基本創建方式torch.tensor 根據指定數據創建張量 &#xff08;最重要&#xff09;torch.Tensor 根據形狀創建張量, 其也可用來創建指定數據的張量torch.IntTensor、torch.FloatTensor、torch.DoubleTensor 創建指定類型的張量1.1 torch.tensor# 方式一&…

3-12〔OSCP ? 研記〕? WEB應用攻擊?利用XSS提權

鄭重聲明&#xff1a; 本文所有安全知識與技術&#xff0c;僅用于探討、研究及學習&#xff0c;嚴禁用于違反國家法律法規的非法活動。對于因不當使用相關內容造成的任何損失或法律責任&#xff0c;本人不承擔任何責任。 如需轉載&#xff0c;請注明出處且不得用于商業盈利。 …

AI 大模型賦能智慧礦山:從政策到落地的全棧解決方案

礦山行業作為能源與工業原料的核心供給端&#xff0c;長期面臨 “安全生產壓力大、人工效率低、技術落地難” 等痛點。隨著 AI 大模型與工業互聯網技術的深度融合&#xff0c;智慧礦山已從 “政策引導” 邁入 “規模化落地” 階段。本文基于 AI 大模型智慧礦山行業解決方案&…

Node.js 項目依賴包管理

h5打開以查看 一、核心理念&#xff1a;從“能用就行”到“精細化管理” 一個規范的依賴管理體系的目標是&#xff1a; 可復現&#xff1a;在任何機器、任何時間都能安裝完全一致的依賴&#xff0c;保證構建結果一致。 清晰可控&#xff1a;明確知道每個依賴為何存在&#x…

洛谷P1835素數密度 詳解

題目如下&#xff1a;這里面有部分代碼比較有意思&#xff1a;1&#xff0c;為何開始先遍歷&#xff0c;最終值小于50000&#xff1f;因為題目要求的右邊與左邊差小于 10^6 &#xff0c;所以最多有10^3個素數&#xff0c;所以保存里面的素數數量大于1000&#xff0c;而50000的化…

突破限制:FileCodeBox遠程文件分享新體驗

文章目錄【視頻教程】1.Docker部署2.簡單使用演示3. 安裝cpolar內網穿透4. 配置公網地址5. 配置固定公網地址在隱私日益重要的今天&#xff0c;FileCodeBox與cpolar的協同為文件傳輸提供了安全高效的解決方案。通過消除公網IP限制和隱私顧慮&#xff0c;讓每個人都能掌控自己的…