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 条件变量是什么? 条件变量为我们提供了另一种 ...
随机推荐
- 递归--练习2--noi6261汉诺塔
递归--练习2--noi6261汉诺塔 一.心得 先把递推公式写出来,会很简单的 二.题目 6261:汉诺塔问题 总时间限制: 1000ms 内存限制: 65536kB 描述 约19世纪末,在欧州 ...
- 第10章 Pry, 强大的pry-rails和相关的几个好用gem
https://asciinema.org/a/0KtCL9HB1bP08wNHLfIeOMa8K 本章讲了如何定位❌,和排除bug. Pry (5000
- bzoj2330: [SCOI2011]糖果 差分约束系统
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候 ...
- 过滤器系列(一)—— Bloom filter
因为要做过滤器相关内容,最近读了一些过滤器方面的文章,准备从中提取主要思想写几篇博客. 作为这系列的第一篇文章,首先得讲一下过滤器是干什么用的.从历史发展来看,过滤器最早出现是作为散列表的替代品,那么 ...
- Psping 实例
PsPing v2.1 https://docs.microsoft.com/zh-cn/sysinternals/downloads/psping 2016/06/29 4 分钟阅读时长 By Ma ...
- POJ 3414 dfs 回溯
题目链接:http://poj.org/problem?id=3414 题意:三个值A, B, C, A和B是两个杯子的容量,问最短操作数使A或者B里的水量是C.有三种操作. 思路:dfs.暴力 很简 ...
- Word 开发资料集合
Word 对象模型概述 https://msdn.microsoft.com/zh-cn/library/kw65a0we.aspx DSOframer微软官方API的查阅方法 http://sh ...
- EPANET头文件解读系列3——TOOLKIT.H
/******************************************************************** TOOLKIT.H - Prototypes for EPA ...
- 安装win7和ubuntu双系统
最近买了新的笔记本电脑,发现新买的电脑上面安装的是win7用户版,在网上查了一下这个版本的win7是功能最少的...另外又发现偌大的500G硬盘居然只给分成2个区,每个250...各种不爽,于是决定格 ...
- CentOS下Docker的安装及国内镜像配置
系统,CentOS 7,最小化安装. 升级包 >$ sudo yum upgrade 安装Docker >$ sudo yum install docker 下面开始配置国内镜像.国外的实 ...