簡體   English   中英

在UNIX系統上調用sleep(0)有什么影響?

[英]What is the effect of calling sleep(0) on a UNIX system?

我看到人們在我使用的大量多線程,多進程應用程序系統的某些部分執行此操作。 它似乎圍繞調試行完成:

std::cerr << "DEBUG: Reaching: " << __FUNCTION__ << " @ " << __LINE__ << std::endl;
sleep(0);

如果我宏睡了(​​0); (即將其更改為“”),系統的調試輸出似乎有不同的順序(不太可預測),所以我認為它使得線路更快出來 - 但我認為std :: cerr是無緩沖的,並且std: :無論如何,endl調用std :: flush(),為什么會這樣呢?

基本上,它可以將控制權交還給調度程序,並讓您立即重新安排。 也就是說,嘗試欺騙操作系統做某事基本上是一種破解。

愚弄操作系統絕不是一個好主意。

如果系統適當地欠載,那么進入休眠狀態將意味着操作系統獲得控制並讓I / O隊列刷新,因此它會產生這種效果。 有時。 根據。

究竟它正在做什么取決於實施的細節,坦白地說,你不能依賴它。

它以難以預測的方式擾亂調度程序。

通常,結果類似於對pthread_yield()的調用 - 您放棄了時間片。 這樣做的結果是,在大量的調試打印負載下,在寫入cerr(即,在那些<< s之間)中,你將不太可能被搶占,因為你將處於時間片的開始在最后一次調試打印之后,因此你不太可能讓多個線程覆蓋彼此的輸出(即得到類似DEBUG: REACHING: foo() @ DEBUG: REACHING bar()17 @ 24 )。

也就是說,這種方法不可靠 - 它擾亂了調度程序,而不是要求特定的語義。 它也很慢 - 無條件地進入內核以產生(並且可能過於頻繁地在多個線程之間彈跳控制)。 並且它不太可能在多核CPU上正常工作。

將mutex放在所有調試輸出上會更好。 也就是說,由於這是調試代碼,因此作者可能使用快速而骯臟的黑客來使其工作得足以調試他們遇到的任何問題也就不足為奇了。

在大多數平台上, sleep(0)會使調度程序或多或少地處理當前線程,就像它已用完了它的時間片一樣。 通常,這意味着,如果可能的話,如果可以運行,則將在該核上安排同一進程中的另一個線程。 正如您所指出的,它傾向於使調度更具可預測性。 對我來說,這在調試時似乎適得其反。

我同意Nemo的評論,它與pthread_yield非常相似。 它確實有一些合法用途,但它有時被錯誤地用作提供更公平或減少延遲的方法。 通常情況下,它會使性能變差,因為上下文切換會破壞緩存。

我看了其他的答案,我同意一般的迷惑感。 我敢打賭除了有人認為更可預測的調度是一件好事之外,沒有充分的理由。 (事實並非如此。靈活性很好。您對調度程序的要求越多,為滿足這些要求而犧牲的就越多。如果您實施的要求實際上並不是必需的,那么您根本無需交易性能。)

您可以使用此方法讓其他進程運行,這可能正在等待某些cpu時間,但如果沒有其他進程正在等待運行,則不會強制執行特定的延遲。

正如其他人所提到的, sleep(0)是一個系統調用,它導致當前線程放棄對CPU的控制。

我能想到的唯一正當理由是使用匯編指令(如LOCK(x86)和)實現自己的同步原語,例如自旋鎖。 LDREX和STREX(ARMv7)。 在這種情況下,如果我們遇到鎖定,我們也可以立即放棄控制,希望另一個線程能夠完成它並鎖定我們的鎖定。 這肯定會消失,直到我們的時間片結束。

話雖如此,在實現自己的同步原語時,您確實需要知道自己在做什么。 具體來說,您可能需要放入內存屏障來強制執行讀寫順序。 使用平台上提供的原語可能要好得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM