[android]同步塊代碼中wait和sleep方法持有鎖狀態的區別

來源:互聯網
上載者:User

標籤:android   sleep   wait   

需求

最近項目中這麼一個功能,希望app監聽android file system,當有檔案create/modify/detele時,app收到通知,把對應的變化資訊告訴伺服器


需求的解決方案

當我們用手機拍照時,會把拍照的檔案儲存在sdcard的DCIM檔案夾下。當檔案產生時,我們會接收到create/modify/write_close訊息,我們要做的是在write_close之後,再發送訊息給伺服器,這樣一來,當我們收到create訊息時,就需要把當前線程阻塞住,直到收到write_close訊息之後再調用notifyAll來開啟阻塞的線程。


問題

問題出在:我們在接收到write_close訊息之後,雖然調用了setState(true),但是isChange的值並沒有馬上改變,而是過了好幾秒之後才被改變


來看看核心代碼
while (count > 0) {  //阻塞線程的代碼,一下代碼簡稱:迴圈synchronized (this) {if (!isChange) { //當isChange不變為true時,一直等待,直到接收到write_close訊息,調用setState(true)try {Log.d(LOG_TAG, "sleeping ......");this.wait(1000);  //這裡原先調用的是TimeUnit.MILLISECONDS.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}continue;}}//...省略代碼sendMsg2Server();結束後break}

public synchronized void setState(boolean isChange){this.isChange = true;this.notifyAll();//原來是沒有加這句,在改成wait(1000)之後,調用notifyAll()}


問題解決方案

把TimeUnit.MILLISECONDS.sleep(1000)改成wait(1000),並且在setState(true)裡notifyAll()。


問題的根源

在if(!isChange)和setState()裡都用了同步塊,同步鎖是this。當我們調用sleep(1000)時,迴圈並沒有交出同步鎖,而是持有鎖直到1秒sleep完成,這時setState()和迴圈會競爭這個this鎖,setState()沒有競爭到這個鎖是很正常的,只要setState()沒有競爭到鎖,迴圈就會sleep 1秒,這樣就會造成列印了好幾句Log.d(LOG_TAG, "sleeping ......");之後才改變isChange的值的情況。


當我們把代碼改成wait(1000)之後,迴圈馬上把鎖交了出去,setState()拿到鎖,馬上改變isChange的值,並且通知迴圈,這樣就能進入後面sendMsg2Server()的代碼了

[android]同步塊代碼中wait和sleep方法持有鎖狀態的區別

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.