2016-11-29 82 views
1

我想問你一些基本的事情,但它真的困擾我很多。 我目前正在爲系統編程學習'pthread mutex',並據我所知,當'pthread_mutex_lock'被調用時,只有當前線程被執行而沒有其他線程被執行。我能這樣想嗎?pthread mutex如何解鎖工作?線程同時出現嗎?

當談到'pthread_mutex_unlock'時,當調用這個函數時,當前線程是否將鎖定權限傳遞給其他線程,並等待其他線程再次解鎖函數?還是包含當前線程的每個線程都同時執行,直到其中一個線程調用鎖定函數?

這裏是我學習的代碼:

#include <stdio.h> 
    #include <stdlib.h> 
    #include <pthread.h> 
    #include <unistd.h> 

    enum { STATE_A, STATE_B } state = STATE_A; 
    pthread_cond_t condA = PTHREAD_COND_INITIALIZER; 
    pthread_cond_t condB = PTHREAD_COND_INITIALIZER; 
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 

    void *threadA() 
    { 
     printf("A start\n"); 
     int i = 0, rValue, loopNum; 

     while(i<3) 
     { 

      pthread_mutex_lock(&mutex); 
      while(state != STATE_A) 
      { 
       printf("a\n"); 
       pthread_cond_wait(&condA, &mutex); 
      } 

      pthread_mutex_unlock(&mutex);  
      pthread_cond_signal(&condB); 


     for(loopNum = 1; loopNum <= 5; loopNum++) 
     { 
      printf("Hello %d\n", loopNum); 
     } 

     pthread_mutex_lock(&mutex); 
     state = STATE_B; 
     printf("STATE_B\n"); 
     pthread_cond_signal(&condB); 
     pthread_mutex_unlock(&mutex); 

     i++; 
    } 

    return 0; 
} 

void *threadB() 
{ 
    printf("B start\n"); 
    int n = 0, rValue; 

    while(n<3) 
    { 
     pthread_mutex_lock(&mutex); 
     while (state != STATE_B) 
     { 
      printf("b\n"); 
      pthread_cond_wait(&condB, &mutex); 
     } 

     pthread_mutex_unlock(&mutex);  
     printf("Goodbye\n"); 
     pthread_mutex_lock(&mutex); 
     state = STATE_A; 
     printf("STATE_A\n"); 
     pthread_cond_signal(&condA); 
     pthread_mutex_unlock(&mutex); 
     n++; 
    } 

    return 0; 
} 

int main(int argc, char *argv[]) 
{ 
    pthread_t a, b; 

    pthread_create(&a, NULL, threadA, NULL); 
    pthread_create(&b, NULL, threadB, NULL); 

    pthread_join(a, NULL); 
    pthread_join(b, NULL); 
} 

我有種修改了一些原廠配件,以確保發生了什麼事在此代碼,如添加的printf(「A開始\ n」)的printf (「a \ n」)等等。

這裏有一些輸出:

輸出1個

B start 
b 
A start 
Hello 1 
Hello 2 
Hello 3 
Hello 4 
Hello 5 
b 
STATE_B 
a 
Goodbye 
STATE_A 
b 
Hello 1 
Hello 2 
Hello 3 
Hello 4 
Hello 5 
b 
STATE_B 
a 
Goodbye 
STATE_A 
b 
Hello 1 
Hello 2 
Hello 3 
Hello 4 
Hello 5 
b 
STATE_B 
Goodbye 
STATE_A 

輸出2

B start 
b 
A start 
Hello 1 
Hello 2 
Hello 3 
Hello 4 
Hello 5 
STATE_B 
a 
Goodbye 
STATE_A 
b 
Hello 1 
Hello 2 
Hello 3 
Hello 4 
Hello 5 
STATE_B 
a 
Goodbye 
STATE_A 
b 
Hello 1 
Hello 2 
Hello 3 
Hello 4 
Hello 5 
STATE_B 
Goodbye 
STATE_A 

所以我才知道,線程調用的時候,他們被同時調用。基於這個邏輯,我在每個線程函數'threadA()和threadB()'的開頭添加了'printf(「A start \ n」)'和'printf(「B start \ n」)'「。但總是'printf(「B start \ n」)'首先出現。如果他們同時被調用,那麼他們是不是必須交替出現,至少是隨機的?因爲我猜想ThreadA中的'pthread_mutex_unlock'調用ThreadB並等待ThreadB調用解鎖函數,所以我假設'Goodbye'消息始終應該早於'a'。我想知道這個代碼是如何工作的。

我猜我會完全錯誤的,誤解了很多部分,因爲我是這個領域的新手。但想得到答案。感謝您閱讀這篇:)

+0

您的問題太過於集中。請一次提出一個具體問題並直接指出問題。如果鎖已被佔用,pthread_mutex_lock將掛起調用線程。當另一個線程調用pthread_mutex_unlock時,內核將選擇當前pthread_mutex_locked被阻塞的線程(如果有的話)並解除阻塞(安排它執行)。 – kaylum

回答

0

當調用'pthread_mutex_lock'時,只執行當前線程 沒有任何其他的。我能這樣想嗎?

我想你可以這樣想,但你會錯誤地思考。 pthread_mutex_lock()不會僅導致調用線程執行。相反,它會執行以下兩項操作之一:

  1. 如果互斥鎖尚未鎖定,它將鎖定互斥鎖並立即返回。
  2. 如果互斥鎖已被鎖定,它會使調用線程進入休眠狀態,等待互斥鎖被解鎖。只有在pthread_mutex_lock()成功獲取鎖定之後,pthread_mutex_lock()纔會返回。

注意,在兩種情況下,pthread_mutex_lock()的承諾,使調用線程是這樣的:當pthread_mutex_lock()的返回零/成功,互斥將被鎖定,調用線程會的主人鎖。 (另一種可能性是,phread_mutex_lock()將返回指示錯誤條件負值,但實際上這是不常見的,所以我不會在上面停留)

,當談到「調用pthread_mutex_unlock」,莫非是當前線程通過 鎖定權限給別人,等到其他線程再次調用 解鎖函數?

要澄清的第一件事是pthread_mutex_unlock()永遠不會等待任何東西;與pthread_mutex_lock()不同,pthread_mutex_unlock()總是立即返回

那麼pthread_mutex_unlock()是做什麼的?

  1. 解鎖互斥量(注意互斥必須已經由先前調用鎖定對pthread_mutex_lock()在同一個線程。如果你調用一個互斥體調用pthread_mutex_unlock(),而不必以前稱爲pthread_mutex_lock()的收購相同的互斥量,那麼你的程序是越野車,將無法正常工作)
  2. 通知操作系統的線程調度程序(通過某些機制,故意留下未記錄,因爲作爲pthreads庫的用戶,你不需要知道或者關心它是如何實現的)該互斥體現在被解鎖。在收到該通知後,操作系統將檢查其他線程(如果有)在自己對pthread_mutex_lock()的調用中被阻塞,等待獲取此互斥鎖,並且如果有任何線程,則會喚醒其中一個線程該線程可能會獲得該鎖,然後可以返回其pthread_mutex_lock()調用。在線程調用pthread_mutex_unlock()之前或之後返回的所有可能情況;執行的確切順序是不確定的,並不重要。

我猜ThreadA中的 '調用pthread_mutex_unlock' 呼籲ThreadB並等待 直到ThreadB電話解鎖功能。

pthread_mutex_unlock()沒有這樣的事情。一般來說,線程不會/不能在其他線程中調用函數。對於pthread_mutex_unlock()做什麼做什麼,請參閱我上面的描述。

0

pthread_mutex_lock()並不意味着只有一個線程將執行 - 它只是意味着任何其他線程試圖調用pthread_mutex_lock()相同的互斥對象上會被暫停,直到第一線程用pthread_mutex_unlock()釋放鎖。

如果其他線程不試圖鎖定相同的互斥鎖,它們可以繼續同時運行。

如果多個線程在第一個線程被鎖定時試圖鎖定相同的互斥鎖,那麼當第一個線程釋放互斥鎖時,只有其中一個線程能夠繼續(然後當該線程本身稱爲pthread_mutex_unlock(),另一個等待線程將能夠繼續等等)。

請注意,等待互斥鎖被解鎖的線程在解鎖互斥鎖時不一定會立即開始執行