Pthreads 信号量,路障,条件变量
▶ 使用信号量来进行线程间信息传递
● 代码
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#pragma comment(lib, "pthreadVC2.lib") const int thread = , messageSize = ;
char messageList[thread][messageSize]; // 全局信息列表
sem_t sem[thread]; // 各线程信号量,注意每个线程都有一个 void* sendMessage(void* rank)
{
const long long localRank = (long long)rank, dest = (localRank + ) % thread;
int i;
sprintf_s(messageList[dest], messageSize, "Hello from %2d to %2d.", localRank, dest);
sem_post(&sem[dest]); // 解锁 dest 的信号量,因为上一行低吗已经完成了写入,注意每次执行完函数 sem_post() 后 sem[dest] 的值增加 1
sem_wait(&sem[localRank]); // 等待自己编号的信号量解锁,注意每次执行完函数 sem_wait() 后 sem[localRank] 的值减小 1(但不会小于0)
printf("Thread %2d > %s\n", localRank, messageList[localRank]);
return nullptr;
} int main()
{
pthread_t pth[thread];
int i;
long long list[thread]; for (i = ; i < thread; i++)
{
sem_init(&sem[i], , ); // 依次初始化信号量
list[i] = i;
pthread_create(&pth[i], nullptr, sendMessage, (void *)list[i]);
}
for (i = ; i < thread; i++)
{
pthread_join(pth[i], nullptr);
sem_destroy(&sem[i]); // 销毁信号量
}
printf("\nfinish.\n");
getchar();
return ;
}
● 输出结果
Thread > Hello from to .
Thread > Hello from to .
Thread > Hello from to .
Thread > Hello from to .
Thread > Hello from to .
Thread > Hello from to .
Thread > Hello from to .
Thread > Hello from to . finish.
● 用到的定义,注意信号量不是由 phread.h 提供的,而是 semaphore.h
typedef struct sem_t_ * sem_t; PTW32_DLLPORT int __cdecl sem_init(sem_t * sem, int pshared, unsigned int value);
// 初始化信号量,输入一个已经声明的信号量的指针,第二个参数不明,第三个参数为 0 表示初始化完成后信号量为上锁状态 PTW32_DLLPORT int __cdecl sem_destroy(sem_t * sem);// 销毁信号量 PTW32_DLLPORT int __cdecl sem_wait(sem_t * sem); // 等待信号量为解锁状态再向下运行 PTW32_DLLPORT int __cdecl sem_post(sem_t * sem); // 解锁信号量
▶ 使用忙等待和互斥量来实现路障
● 代码
#include <stdio.h>
#include <pthread.h>
#pragma comment(lib, "pthreadVC2.lib") const int thread = ;
int count;
pthread_mutex_t pmt; void* work(void* rank)
{
const long long localRank = (long long)rank, dest = (localRank + ) % thread;
pthread_mutex_lock(&pmt); // 进入读写区,上锁,计数器加一,解锁
printf("Thread %2d reached the barrier.\n", localRank); fflush(stdout);
count++;
pthread_mutex_unlock(&pmt);
while (count < thread); // 使用忙等待来等所有的线程都达到栅栏
printf("Thread %2d passed the barrier.\n", localRank); fflush(stdout);
return nullptr;
} int main()
{
pthread_t pth[thread];
int i;
long long list[thread];
pthread_mutex_init(&pmt, nullptr);
for (i = count = ; i < thread; i++)
{
list[i] = i;
pthread_create(&pth[i], nullptr, work, (void *)list[i]);
}
for (i = ; i < thread; i++)
pthread_join(pth[i], nullptr);
pthread_mutex_destroy(&pmt);
printf("\nfinish.\n");
getchar();
return ;
}
● 输出结果
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier. finish.
▶ 使用信号量来实现路障
● 代码
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#pragma comment(lib, "pthreadVC2.lib") const int thread = ;
int count;
sem_t sem_count, sem_barrier; void* work(void* rank)
{
const long long localRank = (long long)rank, dest = (localRank + ) % thread;
printf("Thread %2d reached the barrier.\n", localRank); fflush(stdout);
sem_wait(&sem_count); // 等待允许访问计数器 count,注意执行完该语句时 sem_count 值减 1,自动上锁
if (count == thread - ) // 最后一个到达进入的线程
{
count = ; // 计数器清零,以后可以重复使用
sem_post(&sem_count); // 计数器解锁,sem_count 值加 1
for (int i = ; i < thread - ; sem_post(&sem_barrier), i++);// 解锁整个栅栏,
} // 每有一个线程通过后面的语句 sem_wait(&sem_barrier);,
else // 前面到达的线程 // sem_barrier 的值就减 1,所以这里要为该变量加上 thread - 1
{
count++; // 计数器加一
sem_post(&sem_count); // 解锁计数器
sem_wait(&sem_barrier); // 等待栅栏解锁
}
printf("Thread %2d passed the barrier.\n", localRank); fflush(stdout);
return nullptr;
} int main()
{
pthread_t pth[thread];
int i;
long long list[thread]; sem_init(&sem_count, , ); // 计数器锁初始化为 1,开锁状态
sem_init(&sem_barrier, , ); // 栅栏初始化为 0,关锁状态
for (i = count = ; i < thread; i++)
{
list[i] = i;
pthread_create(&pth[i], nullptr, work, (void *)list[i]);
}
for (i = ; i < thread; i++)
pthread_join(pth[i], nullptr);
sem_destroy(&sem_count), sem_destroy(&sem_barrier);
printf("\nfinish.\n");
getchar();
return ;
}
● 输出结果
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier. finish.
▶ 使用条件变量来实现路障
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#pragma comment(lib, "pthreadVC2.lib") const int thread = ;
int count;
pthread_mutex_t mutex;
pthread_cond_t cond; void* work(void* rank)
{
const long long localRank = (long long)rank, dest = (localRank + ) % thread;
printf("Thread %2d reached the barrier.\n", localRank); fflush(stdout);
pthread_mutex_lock(&mutex); // 上锁
count++;
if (count == thread) // 最后一个进入的线程
{
count = ; // 计数器清零
pthread_cond_broadcast(&cond); // 广播所有线程继续向下执行
}
else
for (; pthread_cond_wait(&cond, &mutex) != ;);// 等待其他线程
pthread_mutex_unlock(&mutex); // 条件变量阻塞解除后会自动将互斥量上锁,需要手工解除 printf("Thread %2d passed the barrier.\n", localRank); fflush(stdout);
return nullptr;
} int main()
{
pthread_t pth[thread];
int i;
long long list[thread];
pthread_mutex_init(&mutex, nullptr);
pthread_cond_init(&cond, nullptr);
for (i = count = ; i < thread; i++)
{
list[i] = i;
pthread_create(&pth[i], nullptr, work, (void *)list[i]);
}
for (i = ; i < thread; i++)
pthread_join(pth[i], nullptr);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
printf("\nfinish.\n");
getchar();
return ;
}
● 输出结果
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread reached the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier.
Thread passed the barrier. finish.
● 用到的定义,pthread.h
typedef struct pthread_cond_t_ * pthread_cond_t; PTW32_DLLPORT int PTW32_CDECL pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr);// 初始化已经声明了的条件变量,第二个参数为属性指针 PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy(pthread_cond_t * cond); // 销毁条件变量 PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex); // 阻塞线程以等待 signal 或 brocast PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal(pthread_cond_t * cond); // 解锁一个线程 PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast(pthread_cond_t * cond); // 解锁所有的线程
Pthreads 信号量,路障,条件变量的更多相关文章
- 学习pthreads,使用条件变量进行多线程之间的同步
条件变量提供另一种多线程同步的方法.互斥量通过控制对共享数据的访问来同步任务.条件变量可以根据数据的值来同步任务.条件变量是当一个事件发生时发送信号的信号量.一旦事件发生,可能会有多个线程在等待信号, ...
- 27 python 初学(信号量、条件变量、同步条件、队列)
参考博客: www.cnblogs.com/yuanchenqi/articles/5733873.html semaphore 信号量: condition 条件变量: event 同步条件:条件 ...
- Python:Day29 信号量、条件变量
信号量:semaphore 信号量是用来控制线程并发数的.(理解:虽然GIL任意时刻都只有一个线程被执行,但是所有线程都有资格去抢,semaphore就是用来控制抢的GIL的数量,只有获取了semap ...
- QThread中的互斥、读写锁、信号量、条件变量
该文出自:http://www.civilnet.cn/bbs/browse.php?topicno=78431 在gemfield的<从pthread到QThread>一文中我们了解了线 ...
- 【Qt开发】QThread中的互斥、读写锁、信号量、条件变量
在gemfield的<从pthread到QThread>一文中我们了解了线程的基本使用,但是有一大部分的内容当时说要放到这片文章里讨论,那就是线程的同步问题.关于这个问题,gemfield ...
- 第二章 信号量及条件变量(三)——> 重点
2.4.4 信号量的应用 1. 利用信号量实现进程互斥 为使多个进程能互斥的访问某临界资源,只需为该资源设置一个互斥信号量mutex,并设置其初值为 1 ,然后讲个进程访问该资源的临界区CS置于w ...
- 进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)
注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...
- linux条件变量使用和与信号量的区别
近来在项目中用到条件变量和信号量做同步时,这一块一直都有了解,但也一直没有总结,这次总结一下,给大家提供点参考,也给自己留点纪念. 首先,关于信号量和条件变量的概念可以自行查看APUE,我这直接把AP ...
- pThreads线程(三) 线程同步--条件变量
条件变量(Condition Variables) 参考资料:http://game-lab.org/posts/posix-thread-cn/#5.1 条件变量是什么? 条件变量为我们提供了另一种 ...
随机推荐
- HttpClient将手机上的数据发送到服务器
到官网下载jar包,下载GA发布版本即可 在项目中将httpclient-4.5.5.jar.httpcore-4.4.9.jar.httpmime-4.5.5.jar.commons-logging ...
- Python环境管理--virtualenvwrapper
遇到问题: 当最近的开发和部署过程中,多个服务器部署的时候发现对于库和包的管理非常混乱,主要有俩个版本问题: 因为业务需要,代码得分别部署在不同的服务器上面,每次部署的时候都得重复的安装包而且不能确定 ...
- const关键字对C++成员函数的修饰
const对C++成员函数的修饰分为三种:1. 修饰参数:2. 修饰返回值:3. 修饰this指针.简述一下知识点如下,以后找功夫再完善. 1. 对函数参数的修饰. 1)const只能用来修饰输入参数 ...
- vim按下ctrl+s僵死
CTRL+S表示停止向终端停止输出 CTRL+Q恢复向终端输出流
- git 基础入门操作
前言: 介绍基础的git入门级指令,虽然git指令非常多,但是实际工作中,我们会用到的非常少,小项目中甚至只需要用到2.3个.而且大部分人都会采用gui,而不是每次都打开终端然后输一长串难记的指令. ...
- (转)OAuth 2.0的设计思路
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版. 本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为R ...
- [置顶]
【机器学习PAI实践十一】机器学习PAI为你自动写歌词,妈妈再也不用担心我的freestyle了(提供数据、代码
背景 最近互联网上出现一个热词就是"freestyle",源于一个比拼rap的综艺节目.在节目中需要大量考验选手的freestyle能力,freestyle指的是rapper即兴的 ...
- 重启Tomcat还可以这样玩的哦
- Swift 获取plist文件展示在TableView上
// 1.定义二维数组 var data:[[String]]! override func viewDidLoad() { super.viewDidLoad() // 2.实例化tableView ...
- [笔记] linux中的计划任务crontab
不能拒绝进步 cron来源于希腊单词chronos(意为"时间"),指linux系统下一个自动执行指定任务的程序(计划任务). 1--crontab 的命令选项 #crontab ...