温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C语言并发编程模型实例分析

发布时间:2022-04-16 09:08:03 来源:亿速云 阅读:211 作者:iii 栏目:开发技术

这篇文章主要介绍“C语言并发编程模型实例分析”,在日常操作中,相信很多人在C语言并发编程模型实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言并发编程模型实例分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1、按照指定的顺序输出

我们执行两个线程:foo1foo2

foo1:打印step1, step3

foo2:打印step2

请用并发使得按照1 2 3 的顺序输出

答:首先两个线程执行顺序不可预判,我们必须保证打印step2之前step1就打印好了,因此需要阻塞一下step2,实现的方式是初始化sem为0,只有打印完step1后(然后进行解锁,V操作)step2才能执行

同理,只有打印完step2后才解开阻塞step3的锁,具体看代码实现就明白了

#include "csapp.c" sem_t step1_done, step2_done; void*  foo1() {     printf("test1 is done\n");     V(&step1_done);                  //step1执行完毕了,那么foo2的阻塞就会被解开     P(&step2_done);                  //测试是否step2执行完毕,     printf("test3 is done\n");     return NULL; } void* foo2() {     P(&step1_done);     printf("test2 is done\n");     V(&step2_done);                  //step2执行完毕,解开打印step的锁     return NULL; } int main() {     pthread_t tid1, tid2;     Sem_init(&step1_done, 0, 0);            //第二个参数为0:在线程之间进行, 第三个参数初始化都为零     Sem_init(&step2_done, 0, 0);     Pthread_create(&tid1, NULL, foo1, NULL);     Pthread_create(&tid2, NULL, foo2, NULL);     //保证线程执行完毕之后主线程才退出,否则线程都执行不了了     Pthread_join(tid1, NULL);     Pthread_join(tid2, NULL);     exit(0); }

2、生产者消费者模型

主要的就是在生产和消费函数中对于信号量的处理

错误实例:

void sbuf_insert(subf_t* sp, int item) {     sem_wait(&sp->mutex);   	sem_wait(&sp->slots);     //将项目放进buf中     sp->buf[(++sp->rear) % (sp->n)] = item;     sem_post(&sp->items);     sem_post(&sp->mutex); } void sbuf_remove(sbuf_t* sp) {   sem_wait(&sp->mutex);   sem_wait(&sp->items);         //do works      sem_post(&sp->slots);   sem_post(&sp->mutex); }

如果我们在处理的时候先拿到 互斥锁,可能就会引起死锁

假设现在buf是满的,生产者拿到了互斥锁,但是自己因为没有空闲被 block…

此时消费者同样因为拿不到互斥锁而被 block…

其他的生产者同样也是没有 互斥锁被block…

解决方法:

比较简单,调换一下顺序就好了。相当于我们生产者、消费者在进行的时候 明确我到底要操控哪个格子 然后再拿mutex????

#include <stdio.h> #include <stdlib.h> #include <semaphore.h> typedef struct sbuf{     int *buf;               /*堆上开辟的内存,用于存储*/     int n;                  /*cap of the buf*/     int front;              //第一个item     int rear;               //最后一个item     sem_t mutex;            //获取临界区的锁     sem_t slots;            //空槽数目     sem_t items;            //已经生产了的数目 }subf_t; void sbuf_init(subf_t* sp, int n) {     sp->n     = n;     sp->buf   = static_cast<int *>(calloc(n, sizeof(int)));     sp->front = 0;     sp->rear  = 0;     sem_init(&sp->mutex, 0, 1);     sem_init(&sp->slots, 0, n);     sem_init(&sp->items, 0, 0); } void sbuf_deinit(subf_t*sp) {     free(sp->buf); } void sbuf_insert(subf_t* sp, int item) {     //首先应该对信号量slots判断,你生产者看中     sem_wait(&sp->slots);     sem_wait(&sp->mutex);     //将项目放进buf中     sp->buf[(++sp->rear) % (sp->n)] = item;     //CSAPP中提到,解锁的顺序一般是和加锁的顺序是相反的     sem_post(&sp->mutex);     sem_post(&sp->items); } int  sbuf_remove(subf_t* sp) {     int item;     sem_wait(&sp->items);       //我看上哪个格子的产品了     sem_wait(&sp->mutex);     item = sp->buf[(++sp->front) % (sp->n)];     sem_post(&sp->mutex);     sem_post(&sp->slots);     return item; }

3、读写锁

第一类读者、写者问题(读者优先)

  • 不会让读者进行等待的,除非现在的权限是写者的

  • 也就是说读者不会因为有一个写者在等待

实现:

信号量:w维护着对于critical section的访问, mutex维护这对于共享变量readcnt(当前在临界区的读者的数量)的访问

每当写者进入了临界区,就对w进行加锁????,离开就解锁。保证了任意时刻临界区最多只能有一个写者

只有第一个读者进入的时候对W加锁,最后一个才释放,那么只要还有一个读者在,其他任意的读者就能够无障碍的进入,同样会导致 写者饥饿

int readcnt = 0; sem_t ,mutex = 1, w = 1; void reader() {   while (1) {     P(&mutex);     readcnt++;     if (readcnt == 1) 	//第一个进入的读者       P(&w);	//上锁,写者不能写了     V(&mutex);	//解开对于readcnt的保护锁          /*     	临界区的工作          */          P(&mutex);     readcnt--;     if (readcnt == 0)        V(&w);	//最后一个读者了, 解开阻塞写者的锁     V(&mutex);	//解开对readcnt的保护锁   } } void writer() {   while (1) {     P(&w);          /*     	临界区工作          */     V(&w);   } }

到此,关于“C语言并发编程模型实例分析”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI