自製Java中的Mutex類

來源:互聯網
上載者:User

標籤:

同步問題中,一個很重要的問題是同步的域,什麼是同步的域呢?簡單以 synchronized 這個關鍵字來說,就是它所同步的範圍。並發編程中很多時候出現的問題沒有選好同步範圍所導致的。但現有的同步關鍵字synchronized所能體現出來的對域的控制,估計用過的的人都說不是很理想。這個時候是不是很懷念Windows下所提供的Mutex操作。

現在為了方便我們自己也可以做一個類似Windows的Mutex的類來方便我們對域的控制,下面看這個類的製作過程。

和製作上一個類一樣,我們先來說一下希望這個類完成的功能:

1.調用getMutexFlag(),僅能是並發的線程中的一個繼續執行,其餘的阻塞。

2.調用freeMutexFlag(),執行的線程離開同步塊(臨界區),並能從阻塞線程中釋放一個線程從getMutexFlag()中返回。

3.getMutexFlag()、freeMutexFlag(),都必須是原子操作。

上面這三個條件其實就是對Windows下Mutex的要求。

已開始我們也許會寫出這樣的代碼:

 1 package com.choi; 2  3 public class MutexFlag { 4  5     protected Thread currentThread = null; 6  7     public synchronized void getMutexFalg() { 8         if (currentThread == null) { 9             currentThread = Thread.currentThread();10         }11         while (currentThread != Thread.currentThread()) {12             try {13                 wait();14                 if (currentThread == null) {15                     currentThread = Thread.currentThread();16                 }17             } catch (Exception e) {18             }19         }20     }21     22     public synchronized void freeMutexFlag(){23         if(currentThread!=null){24             currentThread = null;25             try {26                 notify();27             } catch (Exception e) {28             }29         }30     }31 }

這段代碼看起來是沒有問題的,其實這段代碼運行起來確實是沒有問題的,但我們能把它提供給我們的項目組用嗎?答案是不能的,我們來考慮一種情況:

項目組有三個程式員A,B,C A用這個類寫了一個函數(get到Mutex未釋放),B用這個類寫了一個函數(get到Mutex未釋放),C調用了A和B的函數,用在一個線程中了。則這個線程運行到A時得到了Mutex,運行到B時再去申請Mutex能申請到嗎?看代碼,回答是NO。並申請不到,因為第一個還沒有釋放。Java裡面如果是兩個synchronized嵌套,則沒有問題,第一個得到鎖後,第二個如申請的是同一個鎖,就會自動判斷為已申請到。

我們可以用一個變數來是我們的MutexFlag實現synchronized的嵌套解決方案:

 1 package com.choi; 2  3 public class MutexFlag { 4  5     protected Thread currentThread = null; 6     protected int count = 0; 7  8     public synchronized void getMutexFalg() { 9         while (tryGetMutexFlag() == false) {10             try {11                 wait();12             } catch (InterruptedException e) {13                 e.printStackTrace();14             }15         }16     }17 18     public synchronized boolean tryGetMutexFlag() {19         if (currentThread == null) {20             currentThread = Thread.currentThread();21             count = 1;22             return true;23         }24         if (currentThread == Thread.currentThread()) {25             count++;26             return true;27         }28         return false;29     }30 31     public synchronized void freeMutexFlag() {32         if (currentThread == Thread.currentThread()) {33             count--;34         }35         if (count == 0) {36             currentThread = null;37             notify();38         }39     }40 }

為了編寫方便我把判斷擷取MutexFlag的代碼寫到了同步的tryGetMutexFlag中了,沒申請成功一次就對count做加一操作,每一free都對count做減一操作,那麼當count從新等於零的時候我們就去釋放一個線程擷取MutexFlag。

哦,有人說如果沒有調用get就調用free會有問題,這裡說明一下沒有問題的,因為如果沒有get,currentThread是等於null的,所以count==0,然後就會調用notify,其實沒有問題啦,測試發現,notify不會拋出人異常,相當於空操作。

歡迎到我的GitHub首頁擷取代碼:https://github.com/choitony/Java-MutexFlag-Class/tree/master

自製Java中的Mutex類

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.