<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 同步,第 5 部分:條件變量 > 原文:<https://github.com/angrave/SystemProgramming/wiki/Synchronization%2C-Part-5%3A-Condition-Variables> ## 條件變量簡介 ## 暖身 命名這些屬性! * “CS 中一次只能有一個進程(/ thread)” * “如果等待,那么另一個進程只能進入有限次數的 CS” * “如果 CS 中沒有其他進程,那么進程可以立即進入 CS” 有關答案,請參見[同步,第 4 部分:臨界區問題](/angrave/SystemProgramming/wiki/Synchronization%2C-Part-4%3A-The-Critical-Section-Problem)。 ## 什么是條件變量?你怎么用它們?什么是虛假喚醒? * 條件變量允許一組線程睡眠直到發癢!你可以勾選一個線程或所有正在休眠的線程。如果您只喚醒一個線程,那么操作系統將決定喚醒哪個線程。你不直接喚醒線程,而是“發出”條件變量,然后喚醒條件變量內部的一個(或所有)線程。 * 條件變量與互斥鎖和循環一起使用(以檢查條件)。 * 偶爾等待的線程可能會無緣無故地喚醒(這被稱為 _ 虛假喚醒 _)!這不是問題,因為您總是在循環中使用`wait`來測試必須為 true 才能繼續的條件。 * 通過調用`pthread_cond_broadcast`(全部喚醒)或`pthread_cond_signal`(喚醒一個)喚醒在條件變量內睡眠的線程。注意盡管有函數名稱,這與 POSIX `signal`無關! ## `pthread_cond_wait`有什么作用? 調用`pthread_cond_wait`執行三個操作: * 解鎖互斥鎖 * 等待(在相同的條件變量上調用`pthread_cond_signal`時休眠) * 在返回之前,鎖定互斥鎖 ## (高級主題)為什么條件變量也需要互斥鎖? 條件變量需要互斥鎖有三個原因。最簡單的理解是它可以防止早期喚醒消息(`signal`或`broadcast`功能)被“丟失”。想象一下,在調用 _ `pthread_cond_wait`之前,滿足條件的下列事件序列(時間向下運行)。在這個例子中,喚醒信號丟失了! | 線程 1 | 線程 2 | | --- | --- | | `while( answer &lt; 42) {` | | | | `answer++` | | | `p_cond_signal(cv)` | | `p_cond_wait(cv,m)` | | 如果兩個線程都鎖定了互斥鎖,則在 `pthread_cond_wait(cv, m)`被調用(然后在內部解鎖互斥鎖之后)_ 之前無法發送信號 _ 第二個常見原因是更新程序狀態(`answer`變量)通常需要互斥 - 例如,多個線程可能正在更新`answer`的值。 第三個也是微妙的原因是為了滿足我們在此僅概述的實時調度問題:在時間關鍵型應用中,應該允許具有 _ 最高優先級 _ 的等待線程首先繼續。為滿足此要求,還必須在調用`pthread_cond_signal`或`pthread_cond_broadcast`之前鎖定互斥鎖。對于好奇的人來說,[在](https://groups.google.com/forum/?hl=ky#!msg/comp.programming.threads/wEUgPq541v8/ZByyyS8acqMJ)[中進行了較長時間的歷史性討論。](https://groups.google.com/forum/?hl=ky#!msg/comp.programming.threads/wEUgPq541v8/ZByyyS8acqMJ) ## 為什么存在虛假的尾流? 為了表現。在多 CP??U 系統上,競爭條件可能導致喚醒(信號)請求被忽視。內核可能無法檢測到此丟失的喚醒呼叫,但可以檢測到它何時可能發生。為了避免潛在的丟失信號,線程被喚醒,以便程序代碼可以再次測試條件。 ## 例 條件變量 _ 總是 _ 與互斥鎖一起使用。 在調用 _ 等待 _ 之前,必須鎖定互斥鎖并且 _ 等待 _ 必須用循環包裹。 ```c pthread_cond_t cv; pthread_mutex_t m; int count; // Initialize pthread_cond_init(&cv, NULL); pthread_mutex_init(&m, NULL); count = 0; pthread_mutex_lock(&m); while (count < 10) { pthread_cond_wait(&cv, &m); /* Remember that cond_wait unlocks the mutex before blocking (waiting)! */ /* After unlocking, other threads can claim the mutex. */ /* When this thread is later woken it will */ /* re-lock the mutex before returning */ } pthread_mutex_unlock(&m); //later clean up with pthread_cond_destroy(&cv); and mutex_destroy // In another thread increment count: while (1) { pthread_mutex_lock(&m); count++; pthread_cond_signal(&cv); /* Even though the other thread is woken up it cannot not return */ /* from pthread_cond_wait until we have unlocked the mutex. This is */ /* a good thing! In fact, it is usually the best practice to call */ /* cond_signal or cond_broadcast before unlocking the mutex */ pthread_mutex_unlock(&m); } ``` ## 實現計數信號量 * 我們可以使用條件變量實現計數信號量。 * 每個信號量都需要一個計數,一個條件變量和一個互斥量 ```c typedef struct sem_t { int count; pthread_mutex_t m; pthread_condition_t cv; } sem_t; ``` 實現`sem_init`以初始化互斥鎖和條件變量 ```c int sem_init(sem_t *s, int pshared, int value) { if (pshared) { errno = ENOSYS /* 'Not implemented'*/; return -1;} s->count = value; pthread_mutex_init(&s->m, NULL); pthread_cond_init(&s->cv, NULL); return 0; } ``` 我們`sem_post`的實現需要增加計數。我們還將喚醒在條件變量內部休眠的任何線程。請注意,我們鎖定和解鎖互斥鎖,因此一次只有一個線程可以在臨界區內。 ```c sem_post(sem_t *s) { pthread_mutex_lock(&s->m); s->count++; pthread_cond_signal(&s->cv); /* See note */ /* A woken thread must acquire the lock, so it will also have to wait until we call unlock*/ pthread_mutex_unlock(&s->m); } ``` 如果信號量的計數為零,我們的`sem_wait`實現可能需要休眠。就像`sem_post`一樣,我們使用鎖來包裝臨界區(因此一次只有一個線程可以執行我們的代碼)。請注意,如果線程確實需要等待,那么互斥鎖將被解鎖,允許另一個線程進入`sem_post`并從我們的睡眠中喚醒我們! 請注意,即使線程被喚醒,在它從`pthread_cond_wait`返回之前,它必須重新獲取鎖,因此它必須再等一點(例如,直到 sem_post 結束)。 ```c sem_wait(sem_t *s) { pthread_mutex_lock(&s->m); while (s->count == 0) { pthread_cond_wait(&s->cv, &s->m); /*unlock mutex, wait, relock mutex*/ } s->count--; pthread_mutex_unlock(&s->m); } ``` **等`sem_post`一直調用`pthread_cond_signal`不會破壞 sem_wait?** 答案:不!在計數非零之前,我們無法通過循環。在實踐中,這意味著即使沒有等待線程,`sem_post`也會不必要地調用`pthread_cond_signal`。更有效的實施只會在必要時調用`pthread_cond_signal`,即 ```c /* Did we increment from zero to one- time to signal a thread sleeping inside sem_post */ if (s->count == 1) /* Wake up one waiting thread!*/ pthread_cond_signal(&s->cv); ``` ## 其他信號量考慮因素 * 真實的信號量實現包括隊列和調度問題,以確保公平性和優先級,例如喚醒最高優先級的最長睡眠線程。 * 此外,`sem_init`的高級使用允許跨進程共享信號量。我們的實現僅適用于同一進程內的線程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看