Pthreads 信号量,路障,条件变量

Stella981
• 阅读 1107

▶ 使用信号量来进行线程间信息传递

● 代码

 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 }

● 输出结果

 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);   // 解锁信号量

▶ 使用忙等待和互斥量来实现路障

● 代码

 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 }

● 输出结果

 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.

▶ 使用信号量来实现路障

● 代码

 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 }

● 输出结果

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);                            // 解锁所有的线程
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
ES6 新增的数组的方法
给定一个数组letlist\//wu:武力zhi:智力{id:1,name:'张飞',wu:97,zhi:10},{id:2,name:'诸葛亮',wu:55,zhi:99},{id:3,name:'赵云',wu:97,zhi:66},{id:4,na
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这