Pthreads 信號量,路障,條件變量

▶ 使用信號量來進行線程間信息傳遞函數

● 代碼post

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #include <semaphore.h>
 4 #pragma comment(lib, "pthreadVC2.lib")
 5 
 6 const int thread = 8, messageSize = 100;
 7 char messageList[thread][messageSize];  // 全局信息列表
 8 sem_t sem[thread];                      // 各線程信號量,注意每一個線程都有一個
 9 
10 void* sendMessage(void* rank)
11 {
12     const long long localRank = (long long)rank, dest = (localRank + 1) % thread;
13     int i; 
14     sprintf_s(messageList[dest], messageSize, "Hello from %2d to %2d.", localRank, dest);
15     sem_post(&sem[dest]);               // 解鎖 dest 的信號量,由於上一行低嗎已經完成了寫入,注意每次執行完函數 sem_post() 後 sem[dest] 的值增長 1
16     sem_wait(&sem[localRank]);          // 等待本身編號的信號量解鎖,注意每次執行完函數 sem_wait() 後 sem[localRank] 的值減少 1(但不會小於0)
17     printf("Thread %2d > %s\n", localRank, messageList[localRank]);
18     return nullptr;
19 }
20 
21 int main()
22 {    
23     pthread_t pth[thread];
24     int i;
25     long long list[thread];
26     
27     for (i = 0; i < thread; i++)
28     {
29         sem_init(&sem[i], 0, 0);        // 依次初始化信號量
30         list[i] = i;
31         pthread_create(&pth[i], nullptr, sendMessage, (void *)list[i]);
32     }
33     for (i = 0; i < thread; i++)
34     {
35         pthread_join(pth[i], nullptr);
36         sem_destroy(&sem[i]);           // 銷燬信號量
37     }
38     printf("\nfinish.\n");
39     getchar();
40     return 0;
41 }

● 輸出結果spa

 1 Thread  1 > Hello from  0 to  1.
 2 Thread  2 > Hello from  1 to  2.
 3 Thread  3 > Hello from  2 to  3.
 4 Thread  4 > Hello from  3 to  4.
 5 Thread  5 > Hello from  4 to  5.
 6 Thread  6 > Hello from  5 to  6.
 7 Thread  0 > Hello from  7 to  0.
 8 Thread  7 > Hello from  6 to  7.
 9 
10 finish.

● 用到的定義,注意信號量不是由 phread.h 提供的,而是 semaphore.h線程

 1 typedef struct sem_t_ * sem_t;
 2 
 3 PTW32_DLLPORT int __cdecl sem_init(sem_t * sem, int pshared, unsigned int value);
 4     // 初始化信號量,輸入一個已經聲明的信號量的指針,第二個參數不明,第三個參數爲 0 表示初始化完成後信號量爲上鎖狀態
 5 
 6 PTW32_DLLPORT int __cdecl sem_destroy(sem_t * sem);// 銷燬信號量
 7 
 8 PTW32_DLLPORT int __cdecl sem_wait(sem_t * sem);   // 等待信號量爲解鎖狀態再向下運行
 9 
10 PTW32_DLLPORT int __cdecl sem_post(sem_t * sem);   // 解鎖信號量

 

▶ 使用忙等待和互斥量來實現路障指針

● 代碼code

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #pragma comment(lib, "pthreadVC2.lib")
 4 
 5 const int thread = 8;
 6 int count;
 7 pthread_mutex_t pmt;
 8 
 9 void* work(void* rank)
10 {
11     const long long localRank = (long long)rank, dest = (localRank + 1) % thread;    
12     pthread_mutex_lock(&pmt);   // 進入讀寫區,上鎖,計數器加一,解鎖
13     printf("Thread %2d reached the barrier.\n", localRank); fflush(stdout);
14     count++;
15     pthread_mutex_unlock(&pmt);
16     while (count < thread);     // 使用忙等待來等全部的線程都達到柵欄
17     printf("Thread %2d passed the barrier.\n", localRank); fflush(stdout);
18     return nullptr;
19 }
20 
21 int main()
22 {    
23     pthread_t pth[thread];
24     int i;
25     long long list[thread];
26     pthread_mutex_init(&pmt, nullptr);
27     for (i = count = 0; i < thread; i++)
28     {
29         list[i] = i;
30         pthread_create(&pth[i], nullptr, work, (void *)list[i]);
31     }
32     for (i = 0; i < thread; i++)
33         pthread_join(pth[i], nullptr);
34     pthread_mutex_destroy(&pmt);
35     printf("\nfinish.\n");
36     getchar();
37     return 0;
38 }

● 輸出結果blog

 1 Thread  1 reached the barrier.
 2 Thread  5 reached the barrier.
 3 Thread  2 reached the barrier.
 4 Thread  3 reached the barrier.
 5 Thread  4 reached the barrier.
 6 Thread  0 reached the barrier.
 7 Thread  6 reached the barrier.
 8 Thread  7 reached the barrier.
 9 Thread  5 passed the barrier.
10 Thread  6 passed the barrier.
11 Thread  3 passed the barrier.
12 Thread  0 passed the barrier.
13 Thread  1 passed the barrier.
14 Thread  4 passed the barrier.
15 Thread  2 passed the barrier.
16 Thread  7 passed the barrier.
17 
18 finish.

 

▶ 使用信號量來實現路障get

● 代碼it

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #include <semaphore.h>
 4 #pragma comment(lib, "pthreadVC2.lib")
 5 
 6 const int thread = 8;
 7 int count;
 8 sem_t sem_count, sem_barrier;
 9 
10 void* work(void* rank)
11 {
12     const long long localRank = (long long)rank, dest = (localRank + 1) % thread;        
13     printf("Thread %2d reached the barrier.\n", localRank); fflush(stdout);
14     sem_wait(&sem_count);       // 等待容許訪問計數器 count,注意執行完該語句時 sem_count 值減 1,自動上鎖
15     if (count == thread - 1)    // 最後一個到達進入的線程
16     {
17         count = 0;              // 計數器清零,之後能夠重複使用
18         sem_post(&sem_count);   // 計數器解鎖,sem_count 值加 1
19         for (int i = 0; i < thread - 1; sem_post(&sem_barrier), i++);// 解鎖整個柵欄,
20     }                                                                // 每有一個線程經過後面的語句 sem_wait(&sem_barrier);,
21     else                        // 前面到達的線程                     // sem_barrier 的值就減 1,因此這裏要爲該變量加上 thread - 1 
22     {
23         count++;                // 計數器加一
24         sem_post(&sem_count);   // 解鎖計數器
25         sem_wait(&sem_barrier); // 等待柵欄解鎖
26     }
27     printf("Thread %2d passed the barrier.\n", localRank); fflush(stdout);    
28     return nullptr;
29 }
30 
31 int main()
32 {    
33     pthread_t pth[thread];
34     int i;
35     long long list[thread];
36     
37     sem_init(&sem_count, 0, 1);     // 計數器鎖初始化爲 1,開鎖狀態
38     sem_init(&sem_barrier, 0, 0);   // 柵欄初始化爲 0,關鎖狀態
39     for (i = count = 0; i < thread; i++)
40     {
41         list[i] = i;
42         pthread_create(&pth[i], nullptr, work, (void *)list[i]);
43     }
44     for (i = 0; i < thread; i++)
45         pthread_join(pth[i], nullptr);
46     sem_destroy(&sem_count), sem_destroy(&sem_barrier);
47     printf("\nfinish.\n");
48     getchar();
49     return 0;
50 }

● 輸出結果io

Thread  0 reached the barrier.
Thread  3 reached the barrier.
Thread  4 reached the barrier.
Thread  2 reached the barrier.
Thread  1 reached the barrier.
Thread  5 reached the barrier.
Thread  7 reached the barrier.
Thread  6 reached the barrier.
Thread  4 passed the barrier.
Thread  5 passed the barrier.
Thread  2 passed the barrier.
Thread  7 passed the barrier.
Thread  3 passed the barrier.
Thread  1 passed the barrier.
Thread  6 passed the barrier.
Thread  0 passed the barrier.

finish.

 

▶ 使用條件變量來實現路障

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #include <semaphore.h>
 4 #pragma comment(lib, "pthreadVC2.lib")
 5 
 6 const int thread = 8;
 7 int count;
 8 pthread_mutex_t mutex;
 9 pthread_cond_t cond;
10 
11 void* work(void* rank)
12 {
13     const long long localRank = (long long)rank, dest = (localRank + 1) % thread;        
14     printf("Thread %2d reached the barrier.\n", localRank); fflush(stdout);
15     pthread_mutex_lock(&mutex);         // 上鎖
16     count++;
17     if (count == thread)                // 最後一個進入的線程
18     {
19         count = 0;                      // 計數器清零
20         pthread_cond_broadcast(&cond);  // 廣播全部線程繼續向下執行
21     }
22     else
23         for (; pthread_cond_wait(&cond, &mutex) != 0;);// 等待其餘線程
24     pthread_mutex_unlock(&mutex);       // 條件變量阻塞解除後會自動將互斥量上鎖,須要手工解除    
25     
26     printf("Thread %2d passed the barrier.\n", localRank); fflush(stdout);    
27     return nullptr;
28 }
29 
30 int main()
31 {    
32     pthread_t pth[thread];
33     int i;
34     long long list[thread];
35     pthread_mutex_init(&mutex, nullptr);
36     pthread_cond_init(&cond, nullptr);
37     for (i = count = 0; i < thread; i++)
38     {
39         list[i] = i;
40         pthread_create(&pth[i], nullptr, work, (void *)list[i]);
41     }
42     for (i = 0; i < thread; i++)
43         pthread_join(pth[i], nullptr);
44     pthread_mutex_destroy(&mutex);
45     pthread_cond_destroy(&cond);
46     printf("\nfinish.\n");
47     getchar();
48     return 0;
49 }

● 輸出結果

Thread  0 reached the barrier.
Thread  1 reached the barrier.
Thread  2 reached the barrier.
Thread  4 reached the barrier.
Thread  5 reached the barrier.
Thread  6 reached the barrier.
Thread  7 reached the barrier.
Thread  3 reached the barrier.
Thread  3 passed the barrier.
Thread  0 passed the barrier.
Thread  1 passed the barrier.
Thread  5 passed the barrier.
Thread  4 passed the barrier.
Thread  7 passed the barrier.
Thread  2 passed the barrier.
Thread  6 passed the barrier.

finish.

● 用到的定義,pthread.h

 1 typedef struct pthread_cond_t_ * pthread_cond_t;
 2 
 3 PTW32_DLLPORT int PTW32_CDECL pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr);// 初始化已經聲明瞭的條件變量,第二個參數爲屬性指針
 4 
 5 PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy(pthread_cond_t * cond);                              // 銷燬條件變量
 6 
 7 PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex);        // 阻塞線程以等待 signal 或 brocast
 8 
 9 PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal(pthread_cond_t * cond);                               // 解鎖一個線程
10 
11 PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast(pthread_cond_t * cond);                            // 解鎖全部的線程
相關文章
相關標籤/搜索