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

● 代码

 #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 信号量,路障,条件变量的更多相关文章

  1. 学习pthreads,使用条件变量进行多线程之间的同步

    条件变量提供另一种多线程同步的方法.互斥量通过控制对共享数据的访问来同步任务.条件变量可以根据数据的值来同步任务.条件变量是当一个事件发生时发送信号的信号量.一旦事件发生,可能会有多个线程在等待信号, ...

  2. 27 python 初学(信号量、条件变量、同步条件、队列)

    参考博客: www.cnblogs.com/yuanchenqi/articles/5733873.html  semaphore 信号量: condition 条件变量: event 同步条件:条件 ...

  3. Python:Day29 信号量、条件变量

    信号量:semaphore 信号量是用来控制线程并发数的.(理解:虽然GIL任意时刻都只有一个线程被执行,但是所有线程都有资格去抢,semaphore就是用来控制抢的GIL的数量,只有获取了semap ...

  4. QThread中的互斥、读写锁、信号量、条件变量

    该文出自:http://www.civilnet.cn/bbs/browse.php?topicno=78431 在gemfield的<从pthread到QThread>一文中我们了解了线 ...

  5. 【Qt开发】QThread中的互斥、读写锁、信号量、条件变量

    在gemfield的<从pthread到QThread>一文中我们了解了线程的基本使用,但是有一大部分的内容当时说要放到这片文章里讨论,那就是线程的同步问题.关于这个问题,gemfield ...

  6. 第二章 信号量及条件变量(三)——> 重点

    2.4.4 信号量的应用 1. 利用信号量实现进程互斥   为使多个进程能互斥的访问某临界资源,只需为该资源设置一个互斥信号量mutex,并设置其初值为 1 ,然后讲个进程访问该资源的临界区CS置于w ...

  7. 进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)

    注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...

  8. linux条件变量使用和与信号量的区别

    近来在项目中用到条件变量和信号量做同步时,这一块一直都有了解,但也一直没有总结,这次总结一下,给大家提供点参考,也给自己留点纪念. 首先,关于信号量和条件变量的概念可以自行查看APUE,我这直接把AP ...

  9. pThreads线程(三) 线程同步--条件变量

    条件变量(Condition Variables) 参考资料:http://game-lab.org/posts/posix-thread-cn/#5.1 条件变量是什么? 条件变量为我们提供了另一种 ...

随机推荐

  1. III USP Freshmen ContestH. MaratonIME gets candies

    这题挺有意思的,刚开始不会这交互题,模仿着做了一题就会了,蛮简单 的 这题我用2分,结果wa了,想了一下发现,1到1e9二分50次完全不够用啊,那就转换一下思维,先求出在10^n~10^(n+1)的n ...

  2. 同一sql表,在页面展示多级菜单

    2.

  3. js中字符串处理成数字的方法

    <script> var a="11.1111"; var b="12.2222"; //第一种方法:乘以1的方法 //alert(a*1+b*1) ...

  4. 利用Sonar定制自定义JS扫描规则(一)——sonar环境搭建

    接触sonar已经有段时间了,最早是在一个项目组里面听到这个框架,后来在公司持续集成活动的推动下,也逐渐学习了sonar的具体功能.sonar集成了findbugs,pmd,checkstyle各种静 ...

  5. WebGL编程指南案例解析之绘制一个点

    <!DOCTYPE html> <html> <head> <title>webgl</title> <style type=&quo ...

  6. UML图 之 活动图 (汇总版)

    ============================================================ 摘自: https://blog.csdn.net/tigaoban/arti ...

  7. 重新学习之spring第四个程序,整合struts2+hibernate+spring

    第一步:导入三大框架的jar包(struts2.3.16.1+hibernate3.2+spring3.2.4) 第二步:编写web.xml 和struts.xml和applicationContex ...

  8. How To Enable EPEL Repository in RHEL/CentOS 7/6/5?

    What is EPEL EPEL (Extra Packages for Enterprise Linux) is open source and free community based repo ...

  9. redhat 连接mysql数据库Can't get hostname for your address

    redhat 连接mysql数据库Can't get hostname for your address Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQ ...

  10. SQL Server中的事务与其隔离级别之脏读, 未提交读,不可重复读和幻读

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...