目录1、按照指定的顺序输出2、生产者消费者模型3、读写锁下面代码、思路等来源于b站郭郭 和CSAPP样例,同时希望大家好好读一下CSAPP的内容,真的讲的很好 1、按照指定的顺序输出
下面代码、思路等来源于b站郭郭 和CSAPP样例,同时希望大家好好读一下CSAPP的内容,真的讲的很好
我们执行两个线程:foo1 和foo2
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);
}
主要的就是在生产和消费函数中对于信号量的处理
错误实例:
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;
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;
}
第一类读者、写者问题(读者优先)
实现:
信号量: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语言通过案例讲解并发编程模型的文章就介绍到这了,更多相关C语言 并发编程内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: C语言通过案例讲解并发编程模型
本文链接: https://lsjlt.com/news/146186.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0