<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Vincent.Chan‘s Blog

    常用鏈接

    統計

    積分與排名

    網站

    最新評論

    多線程(5): JT第4章筆記

    第3章主 要介紹了數據的同步(Data Synchronization),這一章則主要介紹線程之間的同步方法(Thread Notification),同樣包括傳統的wait-and-notify方法和JDK 1.5新推出的Condition Variable。在多線程編程中,數據同步和線程同步是兩個最基本也是最關鍵的部分。
    《Java Threads》一書中通過考察打字程序中當按下start和stop按鈕后,每次都創建兩個新的線程的效率問題來引入線程同步的概念,當然不是線程同步 的主要用處。不過,教科書歸教科書,實際運用則又是另一回事。所以,通過書本學習語法,通過實踐來獲得運用經驗。

    4.1 Wait and Notify

    1. 等待/喚醒類似于Solaris或POSIX中的條件變量(conditon variables),或者Windows中的事件變量(evant variable)或者信號量(signal),用于某個/多個線程暫停等待某個條件的滿足,而該條件將由其它線程來設置的情況。
    2. 在Java中,就像每個對象有一個鎖之外,任何對象都可以提供等待/喚醒的機制。就像Java中的synchronized總是表示獲得某個具體對象的鎖 一樣,wait和notify也總是等待某個具體的對象,并由該對象喚醒;同樣,獲得某個對象上的鎖不一定是該對象需要同步一樣,等待和喚醒的條件也不一 定是與之綁定的對象。
    3. Java中wait-and-notify的幾個方法:
    void wait(): 使當前線程處于等待狀態,直到其它線程調用了nofity()或者notifyAll()方法為止。
    void wait(long timeout): 使當前線程處于等待狀態,直到其它線程調用了nofity()或者notifyAll()方法,或者超過了指定的時間(單位為ms)為止
    void wait(long timeout, int nanos):與wait(long)一樣,只是在某些JVM中可以精確到奈秒。
    void notify(): 喚醒一個正在等待該對象的線程。
    void notifyAll(): 喚醒所有正在等待該對象的線程。
    注意:任何等待和喚醒方法都必須在與之對應的對象的同步方法或同步塊里調用。即:wait-and-notify必須和與之對應的synchronized關鍵詞一起使用的。
    4. wait()和sleep()的主要區別:
      1) sleep()可以在任何地方調用,而wait()需要在同步方法或同步塊中調用;
       2) 進入wait()函數時,JVM會自動釋放鎖,而當從wait()返回即被喚醒時,又會自動獲得鎖;而sleep()沒有這個功能,因此如果在wait ()的地方用sleep()代替,則會導致相應的nofity()方法在等待時不可能被觸發,因為notify()必須在相應的同步方法或同步塊中,而此 時這個鎖卻被sleep()所在的方法占用。也就是說,wait-and-notify不可能與sleep()同時使用。

    4.1.1 The Wait-and-Notify Mechanism and Synchronization
    1. 這一節詳細的講解了wait-and-notify機制和synchronized的關系,主要是兩點:1)wait-and-notify必須和synchronized同時使用;2)wait()會自動釋放和獲取鎖;
    2. 這一節中舉了一個例子用來解釋可能存在當條件被不滿足時也有可能被喚醒的情況:
      1) 線程T1調用一個同步方法;
      2) T1檢測狀態變量,發現其不滿足條件;
      3) T1調用wait(),并釋放鎖;
      4) 線程T2調用另外一個同步方法,獲得鎖;
      5) 線程T3調用另外一個同步方法,由于T2獲得了鎖,所以處于等待狀態;
      6) T2修改狀態變量,使其滿足條件,并調用notify()方法;
      7) T3獲得鎖,然后處理數據,并將狀態變量又設置為不滿足條件的狀態;
      8) T3處理完畢返回;
      9) T1被喚醒,但實際上此時條件并不滿足。
    這個例子剛好印證了《Effective Java》中"Item 50: Never invoke wait outside a loop"和《Practical Java》中"實踐54:針對wait()和notifyAll()使用旋鎖(spin locks)"。即總是用下面這種方式來調用wait():
        synchronized(obj) {
    while(<condition does not hold>)
    wait();


    ... // Perform action appropriate to condition
    }
    或者象《Practical Java》中一樣:
        synchronized(obj) {
    while(<condition does not hold>) {
    try {
    wait();
    } catch (InterruptedException e) {}
    }


    ... // Perform action appropriate to condition
    }
    3. 調用wait()的線程T可能在以下幾種情況被喚醒:
      1) 其它線程調用了notify(),而剛好線程T得到了通知;
      2) 其它線程調用了notifyAll();
      3) 其它線程中斷了線程T;
      4) 由于JVM的原因,導致了spurious wakeup。

    4.1.2 wait(), notify(), and notifyAll()
    1. 正像多個線程等待同一對象上的鎖,當鎖釋放時,無法確定哪個線程會得到那個鎖一樣;當有多個線程在wait()時,當另外一個線程調用nofity()的 時候,也不能確定哪個線程會被喚醒; 2. 因此在《Practical Java》的"實踐53:優先使用notifyAll()而非notify()"建議的一樣,結合實踐54,可以比較好的解決線程喚醒的問題。

    4.1.3 Wait-and-Notify Mechanism with Synchronized blocks
    再次強調必須在同一個對象的synchronized方法或塊內調用該對象上的wait和notify方法。

    4.2 Condition Variables

    1. 就像上面反復強調的一樣,wait-and-notify機制是與特定對象及其上的鎖是綁定在一起的,鎖和喚醒對象不能分開,這在某些情況下不是很方便;
    2. JDK 1.5提供Condition接口來提供與其它系統幾乎一致的condition variables機制;
    3. Condition對象由Lock對象的newCondition()方法生成,從而允許一個鎖產生多個條件變量,可以根據實際情況來等待不同條件;
    4. 該書的例子沒有什么特別的實際意義,但JDK 1.5文檔中提供了一個例子,能充分說明使用Condition Variables使得程序更加清晰易讀,也更有效率:
    class BoundedBuffer {
    final Lock lock = new ReentrantLock();
    final Condition notFull = lock.newCondition();
    final Condition notEmpty = lock.newCondition();
    final Object[] items = new Object[100];
    int putptr, takeptr, count;


    public void put(Object x) throws InterruptedException {
    lock.lock();
    try {
    while (count == items.length)
    notFull.await();
    items[putptr] = x;
    if (++putptr == items.length) putptr = 0;
    ++count;
    notEmpty.signal();
    } finally {
    lock.unlock();
    }
    }

    public Object take() throws InterruptedException {
    lock.lock();
    try {
    while (count == 0)
    notEmpty.await();
    Object x = items[takeptr];
    if (++takeptr == items.length) takeptr = 0;
    --count;
    notFull.signal();
    return x;
    } finally {
    lock.unlock();
    }
    }
    }
    具體的說明請參考JDK 1.5的文檔。
    5. 除了用lock和await-and-signal來代替synchronized和wait-and-notify外,其語義和機制基本一樣。await()在進入前也會自動釋放鎖,然后再返回前重新獲得鎖;
    6. 使用Condition Variables的原因:
      1) 如果使用Lock對象,則必須使用condition variables;
      2) 每個Lock對象可以創建多個condition variable.

    posted on 2006-03-09 23:00 Vincent.Chen 閱讀(93) 評論(0)  編輯  收藏 所屬分類: Java

    主站蜘蛛池模板: 亚洲资源在线视频| 亚洲成人在线电影| 亚洲国产成人无码AV在线| 一色屋成人免费精品网站| 亚洲妇女水蜜桃av网网站| 91成人免费观看| 亚洲伊人久久大香线蕉苏妲己| 丝袜捆绑调教视频免费区| 国产亚洲3p无码一区二区| 黄网站免费在线观看| 亚洲激情在线视频| 又黄又爽又成人免费视频| 色婷五月综激情亚洲综合| 免费观看理论片毛片| 美女尿口扒开图片免费| 国产亚洲情侣一区二区无码AV| 99久久99这里只有免费的精品 | 国产精品亚洲二区在线| mm1313亚洲精品国产| 国产成人1024精品免费| 亚洲va在线va天堂va888www| 免费看又黄又无码的网站| 亚洲avav天堂av在线网爱情| 免费永久国产在线视频| 羞羞视频免费网站在线看| 久久精品国产亚洲av麻豆小说 | 久久青草亚洲AV无码麻豆| 91成人免费观看| 亚洲av永久中文无码精品综合| 亚洲不卡AV影片在线播放| 成全动漫视频在线观看免费高清版下载| 亚洲熟妇无码爱v在线观看| 免费涩涩在线视频网| 成人国产精品免费视频| 亚洲大香人伊一本线| 免费一看一级毛片人| 在线人成精品免费视频| 国产综合激情在线亚洲第一页| 亚洲AV无码不卡无码| 日韩免费电影在线观看| 免费国产午夜高清在线视频 |