多線程同步中sleep與wait區別


1、函數
wait是Object的一個函數,指線程處於進入等待狀態,此時線程不佔用任何資源,不增加時間限制。wait可以被notify和notifyAll函數喚醒(這兩個也是Object的函數)。

sleep則是Thread的一個函數,指線程被調用時,佔着CPU不工作.此時,系統的CPU部分資源被佔用,其他線程無法進入,會增加時間限制。

所以
sleep(100L)意思爲:佔用CPU,線程休眠100毫秒
wait(100L)意思爲:不佔用CPU,線程等待100毫秒

注意:wait和sleep最終都是調用native函數。


2、多線程
使用多線程就沒法繞過同步問題,而wait和sleep對於同步鎖也有不同的效果
(1)在使用上,調用obj的wait和notify函數前必須獲取對象鎖,即在synchronized(obj){...}代碼塊中。
(2)如果都在synchronized代碼塊中,wait(obj)函數可以釋放鎖,而sleep函數則不釋放鎖。
在wait釋放鎖這裏有一個場景:
有兩個線程A和B,在A線程中有如下代碼:
synchronized(mLock){
     ...
     mLock.wait();
     ...
}
這樣在synchronized處獲取對象鎖,當執行到wait函數時,線程A進入等待狀態,並且釋放對象鎖。
在B線程中有如下代碼:
synchronized(mLock){
     ...
     mLock.notify();
     ...
}
當A的wait函數釋放鎖時,B線程的synchronized獲取了對象鎖,開始執行代碼。
當執行到notify函數時,喚醒A線程。但是這時由於B的synchronized代碼塊未執行完,所以未釋放鎖。所以先執行B線程notify後面的代碼,Bsynchronized代碼執行完後釋放鎖,A線程獲取鎖並執行wait之後的代碼。
(注意,如果有多個wait狀態的obj,notify函數只能喚醒其中一個,是由JVM決定的,而notifyAll可以喚醒所有的)

測試代碼如下:
Thread a = new Thread(new Runnable() {
    @Override
    public void run() {
        synchronized (mLock){
            Log.e("sss", "a 1");
            try {
                mLock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.e("sss", "a 2");
        }
    }
});
Thread b = new Thread(new Runnable() {
    @Override
    public void run() {
        synchronized (mLock){
            Log.e("sss", "b 1");
            try {
                mLock.notify();
            } catch (Exception e) {
                e.printStackTrace();
            }
            Log.e("sss", "b 2");
        }
    }
});
a.start();
b.start();
打印日誌如下:
12-14 18:50:12.909 22793-22824/com.example.testapplication E/sss: a 1
12-14 18:50:12.909 22793-22825/com.example.testapplication E/sss: b 1
12-14 18:50:12.909 22793-22825/com.example.testapplication E/sss: b 2
12-14 18:50:12.909 22793-22824/com.example.testapplication E/sss: a 2




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