- 操作系統: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_for | sleep_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 控制“什么時候開始”。
它們是多線程中實現節流、重試、定時、同步啟動等行為的基礎工具,理解其差異和適用場景,能讓你寫出更健壯的并發程序。