管程(Monitor)概念及Java的實現原理_網頁設計公司

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

目錄

  • 互斥
  • 管程-Monitor
  • 當線程等待資源時
  • Hoare版本
  • Mesa版本
  • Brinch Hanson版本
  • 三種語義對比
  • Java版本的Monitor
  • Java monitor實現生產者/消費者

互斥

互斥訪問是併發編程要解決的核心問題之一。
有許多種方法可以滿足臨界區的互斥訪問。大體上可以分為三種,
一種是軟件方法,即由用戶程序承擔互斥訪問的責任,而不需要依賴編程語言或操作系統,譬如Dekker算法、Peterson算法等,通常這種方式會有一定的性能開銷和編程難度。
第二種是操作系統或編程語言對互斥的原生支持,譬如Linux中的mutex、Java語言的synchronized。
最後是硬件上的特殊指令,譬如著名的CAS。這種方式開銷最少,但是很難成為一種通用的解決方案,通常操作系統或編程語言的互斥是基於此建立起來的。

管程-Monitor

管程屬於編程語言級別的互斥解決方案,最早是Brinch Hanson和Hoare於1970s提出的概念,已在Pascal、Java、Python等語言中得到了實現。
“管程”一詞翻譯自英文Monitor Procedures,字面理解就是管理一個或多個執行過程。(但是個人感覺“管程”這個翻譯有點莫名其妙,看完更迷糊了,所以本文堅持用回原名Monitor。)
Monitor本質上是對通用同步工具的一種抽象,它就像一個線程安全的盒子,用戶程序把一個方法或過程(代碼塊)放進去,它就可以為他們提供一種保障:同一時刻只能有一個進程/線程執行該方法或過程,從而簡化了併發應用的開發難度
如果Monitor內沒有線程正在執行,則線程可以進入Monitor執行方法,否則該線程被放入入口隊列(entry queue)並使其掛起。當有線程從Monitor中退出時,會喚醒entry queue中的一個線程。
為了處理併發線程,Monitor還需要一個更基礎的同步工具,或者說需要一個機制,使得線程不僅被掛起,而且還能釋放Monitor,以便其他線程可以進入。
Monitor使用條件變量(Condition Variable)支持這種機制,這些條件變量(一個或多個)包含在Monitor中,並且只有在Monitor內才能被訪問 (類似Java對象的private變量)。
對外開放兩個方法以便用戶程序操作條件變量
cwait(c):調用該方法的線程在條件c上阻塞,monitor現在可以被其他線程使用。
csignal(c):恢復在條件c上被阻塞的線程。若有多個這樣的線程,選擇其中一個。
(通常,為了保證cwait/csignal對條件變量的變更是原子性的,還需要藉助CAS)

當線程等待資源時

當Monitor中正在執行的線程無法獲取所需資源時,情況會變得更加複雜。
如果發生這種情況,等待資源的線程可以先把自己掛起,並且釋放Monitor的使用權,使得其他線程得以進入Monitor。
那麼問題來了,當第二個線程在執行期間,第一個線程所需的資源可用了,會發生什麼?
立即喚醒第一個線程,還是第二個線程先執行完?
對此產生了多個對Monitor的定義。

Hoare版本

在Hoare的語義中,當資源可用時,ThreadA立即恢復執行,而ThreadB進入signal queue。

1.ThreadA 進入 monitor
2.ThreadA 等待資源 (進入wait queue)
3.ThreadB 進入monitor
4.ThreadB 資源可用 ,通知ThreadA恢復執行,並把自己轉移到signal queue。
5.ThreadA 重新進入 monitor
6.ThreadA 離開monitor
7.ThreadB 重新進入 monitor
8.ThreadB 離開monitor
9.其他在entry queue中的線程通過競爭進入monitor

Mesa版本

在Mesa Monitor的實現中,第二個線程會先執行完。
ThreadA的資源可用時,把它從wait queue轉移到entry queue。ThreadB繼續執行至結束。
ThreadA最終也會從entry queue中得以執行。

1.ThreadA 進入 monitor
2.ThreadA 等待資源 (進入wait queue,並釋放monitor)
3.ThreadB 進入monitor
4.ThreadB 資源可用,通知ThreadA。(ThreadA被轉移到entey queue)
5.ThreadB 繼續執行
6.ThreadB 離開monitor
7.ThreadA 獲得執行機會,從entry queue出隊列,恢復執行
8.ThreadA 離開monitor
9.其他在entry queue中的線程通過競爭進入monitor

由於ThreadA被轉移到了entry queue,當ThreadB退出monitor后,ThreadA與其他線程平等競爭monitor的進入條件,所以並不能保證立即執行。
更不幸的是,等到ThreadA重入monitor后,資源可能再次不可用,重複以上過程。

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

Brinch Hanson版本

Brinch Hanson Monitor(以下簡稱BH Monitor)只允許線程從monitor退出時發出信號,此時被通知的線程進入monitor恢復執行。

1.ThreadA 進入 monitor
2.ThreadA 等待資源a
3.ThreadB 進入monitor
4.ThreadB 離開Monitor,並給通知等待資源a的線程,資源可用
5.ThreadA 重新進入 monitor
6.ThreadA 離開monitor
7.其他線程從entry queue中競爭進入monitor

三種語義對比

Hoare Monitor中,資源可用時,ThreadB調用csignal()后被阻塞,以便ThreadA立即恢復執行。
這時ThreadB應該被放到哪裡?一種可能是轉移到entry queue,這樣它就必須與其他還未進入Montior的線程平等競爭獲取重入機會。
但是由於在調用csignal()之前,ThreadB已經執行了一部分,因此使它優先於其他線程是有意義的,
為此,Hoare Monitor增加了signal queue用於存放阻塞在csignal()上的線程。
Hoare Monitor的一個明顯缺點是,ThreadB在執行中途被中斷,需要額外的兩次線程切換才能恢復執行。
不同的是,Mesa Monitor和BH Monitor會保證ThreadB先執行完,因此不需要額外的signal queue。

Java版本的Monitor

Java在實現時對最初的Monitor定義做了一些合理的限制。首先,與以上三種都不一樣的是,Java Montior只允許一個條件變量,而不是多個。

不像BH monitor,signal可以出現在代碼的任何地方。

也不像Hoare monitor,資源可以時,被通知的線程不會立即執行,而是從BLOCK狀態變成RUNNABLE狀態,被CPU再次調度到時才恢復執行。

與cwait(c)和csignal(c)對應的是wait()和notify()方法。

Java monitor機制通過synchronized關鍵字暴露給用戶,syncronized可以修飾方法或代碼塊(兩者本質上都是一個過程)。

Java monitor實現生產者/消費者



//簡化版本,只允許一個生產者和一個消費者

class BoundedBuffer {    

   private int numSlots = 0;

   private double[] buffer = null;

   private int putIn = 0, takeOut = 0;

   private int count = 0;



   public BoundedBuffer(int numSlots) {

      if (numSlots <= 0) throw new IllegalArgumentException("numSlots<=0");

      this.numSlots = numSlots;

      buffer = new double[numSlots];

      System.out.println("BoundedBuffer alive, numSlots=" + numSlots);

   }



   public synchronized void deposit(double value) {

      while (count == numSlots)

         try {

            wait();

         } catch (InterruptedException e) {

            System.err.println("interrupted out of wait");

         }

      buffer[putIn] = value;

      putIn = (putIn + 1) % numSlots;

      count++;                  

      if (count == 1) notify();  //喚醒等待的consumer

   }



   public synchronized double fetch() {

      double value;

      while (count == 0)

         try {

            wait();

         } catch (InterruptedException e) {

            System.err.println("interrupted out of wait");

         }

      value = buffer[takeOut];

      takeOut = (takeOut + 1) % numSlots;

      count--;                           // wake up the producer

      if (count == numSlots-1) notify(); // 喚醒等待的producer

      return value;

   }

}

1.Monitors and Condition Variables:https://cseweb.ucsd.edu/classes/sp17/cse120-a/applications/ln/lecture8.html
2.《操作系統精髓與設計原理》第五章
3.https://en.m.wikipedia.org/wiki/Monitor_(synchronization)

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。