簡體   English   中英

Thread.Yield與WaitOne

[英]Thread.Yield vs. WaitOne

據我了解, Thread.Yield發出線程信號的目的,可以使用Thread.Yield代替WaitOneManualResetEvent

盡管我還沒有看到一個文檔來解釋WaitOne在幕后的確切行為,但我認為它將線程置於Wait狀態,並告訴OS調度程序每次在該線程輪到時檢查是否設置了ManualResetEvent 。隊列。 如果未設置,則調度程序不執行上下文切換,而是跳到另一個線程。 如果設置,則調度程序將線程置於運行狀態,以便WaitOne之后的代碼開始執行。

另一方面,無論ManualResetEvent的狀態如何,使用Thread.Yield都將導致上下文切換,然后進行檢查。

我的理解正確嗎? 是否有文檔解釋WaitOne的內部工作原理?

PS:這是用於演示目的的兩個版本的示例代碼:

var signal = new ManualResetEvent(false);
new Thread(() =>
{
    Console.WriteLine("Waiting for signal...");
    signal.WaitOne();
    signal.Dispose();
    Console.WriteLine("Got signal!");
}).Start();
Thread.Sleep(2000);
signal.Set(); // "Open" the signal

bool signal = false;
new Thread(() =>
{
    Debug.WriteLine("Waiting for signal...");
    while(signal == false)
    {
        Thread.Yield();
    }
    Debug.WriteLine("Got signal!");
}).Start();
Thread.Sleep(2000);
signal = true; ; // "Open" the signal

首先,漢斯的評論是完全正確的:您正在發明自己的旋轉等待,非常糟糕。 不要那樣做!

就是說,您的問題不是關於是否應該重新實現WaitOne,而是因為沒有編寫WaitOne的人是如何實現WaitOne的。 考慮這個問題是完全合理的; 這些功能不是神奇的,而是由人類實現的,那么它們是如何做到的呢?

這是一個實現細節,我沒有方便的運行時源代碼。 實際的實現是在名為WaitOneNative的本機函數中WaitOneNative 但是,我可以給您一些想法。

首先,您正確地注意到Thread.Yield是更原始的操作,因此可以將其用作構建諸如WaitOne類的更高級別操作的策略的一部分。 但是實際上,由於以下幾個原因,可能不會以您描述的幼稚方式使用它:

  • Thread.Yield確實會創建一個障礙,但是從代碼中並不是100%顯而易見的是沒有消除對bool的讀取,或者不能延遲寫入。 我們要非常非常確定地確定布爾寫操作,並且引入障礙不會破壞性能。

  • Thread.Yield將控制權Thread.Yield當前處理器上的任何就緒線程。 如果當前處理器上沒有就緒線程,該怎么辦? 也許考慮一下。 是什么使該代碼無法加熱整個CPU? 如果要執行寫操作的線程在不同的處理器上會發生什么? 涉及線程匱乏等所有可能的方案是什么?

  • 考慮這種情況:我們有一個具有三個線程的超線程處理器,Alpha,Bravo和Charlie,並且Alpha和Bravo當前正在CPU中執行。 Alpha的量子剩余時間為1000萬納秒,它發現該標志是錯誤的,並將其剩余的量子提供給Charlie。 一納秒后,Bravo設置了標志。 我們只承擔了上下文切換的全部費用,而Alpha放棄了進行一千萬納秒工作的機會! 對於Alpha來說,旋轉等待並消耗其一千萬納秒中的幾十個,而不是花費上下文切換的巨額成本會更好。 在設計新的線程原語時,必須考慮這些情況 僅使控制流程正確還不夠。 您在熱路徑上做出錯誤的決定,可能會使性能降低數千或數百萬。

  • 等等。

但是,等等,情況變得更糟。 WaitOne是否需要解決更多細微的問題?

當然。 CLR具有必須維護的不變式。 您必須記住, CLR是從根本上發明的,是對COM的擴展 ,其底層實現已深深地嵌入到COM世界中。 特別是,關於編組的所有規則仍然適用。 WaitOne有效地使線程進入睡眠狀態,但是這可能導致編組器出現問題。 克里斯·布魯姆(Chris Brumme)在這方面的文章特別令人恐懼和困擾:

https://blogs.msdn.microsoft.com/cbrumme/2004/02/02/apartments-and-pumping-in-the-clr/

閱讀它,看看您是否能理解所有內容。 自2004年以來,我已經閱讀了數十次,而且我曾經是一名專業的COM程序員,我大概得到了其中的80%。 這是一件很復雜的事情,如果您不了解,您將無法編寫滿足CLR需求的WaitOne正確實現。

暫無
暫無

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

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