根據java文檔全面解析Thread.yield()方法

    /**(1)
     * A hint to the scheduler that the current thread is willing to yield
     * its current use of a processor. The scheduler is free to ignore this
     * hint.
     *(2)
     * <p> Yield is a heuristic attempt to improve relative progression
     * between threads that would otherwise over-utilise a CPU. Its use
     * should be combined with detailed profiling and benchmarking to
     * ensure that it actually has the desired effect.
     *(3)
     * <p> It is rarely appropriate to use this method. It may be useful
     * for debugging or testing purposes, where it may help to reproduce
     * bugs due to race conditions. It may also be useful when designing
     * concurrency control constructs such as the ones in the
     * {@link java.util.concurrent.locks} package.
     */
     public static native void yield();

(1)當前線程暗示調度器,它願意讓出對CPU的使用。調度器可以忽略這個暗示,也可以做出相應處理。

    說明:如果調度器忽略了這個暗示,那麼當前線程將會繼續執行,不會停止。如果調度器沒有忽略,則當前線程會從執行狀態轉化爲就緒狀態,然後調度器會從就緒狀態的線程中,選擇一個出來,讓它使用CPU。

(2)yield方法的初衷是爲了提高線程之間的相對進度,防止過度使用CPU的。所以yield方法的使用,一定要經過詳細的分析和測試,確保yield能達到預期的效果。

    說明:也就是說要知道yield方法可能會被忽略。我們要在這個前提下,去正確使用yield。

(3)適合yield方式使用的場景不多。有需要使用到的地方,一個是競態條件下爲了復現bug,使用yield用於調試。另一個是同步控制的設計需要。

下面舉個例子,說明一個yield的使用場景(一定是和while()循環搭配使用的):

  public static void main(String[] args) throws InterruptedException {
        final AtomicInteger ai = new AtomicInteger(1);
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!ai.compareAndSet(2, 3))
                    Thread.yield();//當ai的值還沒有被賦值爲2的時候,線程讓出CPU使用權
            }
        });

        t.start();
        if (ai.compareAndSet(1, 2)) {//將2賦值給ai
            t.join();//等待t線程運行完再往下執行,相當於把線程t的代碼加進來了
            if (!t.isAlive()) {
                int a = ai.get();
                System.out.println("a = " + a);//a = 3
            } else {
                System.out.println("t線程還在運行中");//如果t.join()註釋掉的話,會打印這句,否則永遠不會打印
            }
        }
    }

可以看出來,t 線程想要把ai的值從2更新爲3,需要等待主線的把ai的值從1更新爲2以後。所以線程 t 在更新ai值失敗以後,調用yield方法,讓出了cpu的使用權。如果這時候被調度器忽略的,會繼續去更新ai的值。這是ai的值可能是2了,也可能不是。如果不是,t線程會繼續重複上述步驟,直到成功賦值爲3。(和我們預期的是一樣的)

 

覺得有用的老鐵們贊一下唄,謝謝!

發佈了86 篇原創文章 · 獲贊 144 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章