Linux 信号量之Posix基于内存的信号量
程序员文章站
2022-10-24 14:59:04
信号量(semaphore),也和互斥锁一样提供了线程间或者进程间的同步功能。 信号量有三种: "Posix有名字的信号量" Posix基于内存的信号量 System V信号量 信号量比互斥锁高级,互斥锁只允许一个线程访问临界区,信号量可以多个,可以把信号量看作成互斥锁的升级版,但是如果能用互斥锁解 ......
信号量(semaphore),也和互斥锁一样提供了线程间或者进程间的同步功能。
信号量有三种:
- posix有名字的信号量
- posix基于内存的信号量
- system v信号量
信号量比互斥锁高级,互斥锁只允许一个线程访问临界区,信号量可以多个,可以把信号量看作成互斥锁的升级版,但是如果能用互斥锁解决,就用互斥锁,互斥锁比信号量节省资源。
这篇文章只介绍posix基于内存的信号量
1,单个生产者和单个消费者
#include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <sys/stat.h> #include <semaphore.h> #define nbuff 10 int nitems; struct { int buff[nbuff]; sem_t mutex, nempty, nstored; } shared; void* produce(void *args); void* consume(void* args); int main(int argc, char** argv){ pthread_t tid_produce, tid_consume; if(argc != 2){ printf("usage error\n"); exit(1); } nitems = atoi(argv[1]); //create 3 semaphore sem_init(&shared.mutex, 0, 1); sem_init(&shared.nempty, 0, nbuff); sem_init(&shared.nstored, 0, 0); pthread_create(&tid_produce, null, produce, null); pthread_create(&tid_consume, null, consume, null); pthread_join(tid_produce, null); pthread_join(tid_consume, null); sem_destroy(&shared.mutex); sem_destroy(&shared.nempty); sem_destroy(&shared.nstored); exit(0); } void* produce(void *args){ int i; for(i = 0; i < nitems; ++i){ sem_wait(&shared.nempty); sem_wait(&shared.mutex); shared.buff[i % nbuff] = i; sem_post(&shared.mutex); sem_post(&shared.nstored); } return null; } void* consume(void* args){ int i; for(i = 0; i < nitems; ++i){ sem_wait(&shared.nstored); sem_wait(&shared.mutex); shared.buff[i % nbuff] = i; sem_post(&shared.mutex); sem_post(&shared.nempty); } return null; }
2,多个生产者和单个消费者
#include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <sys/stat.h> #include <semaphore.h> #define nbuff 10 #define maxthrs 100 #define min(x,y) ( x > y ? y:x ) int nitems, nproducers; struct { int buff[nbuff]; int idx; int val; sem_t mutex, nempty, nstored; } shared; void* produce(void *args); void* consume(void* args); int main(int argc, char** argv){ int i, count[maxthrs]; pthread_t tid_produce[maxthrs], tid_consume; if(argc != 3){ printf("usage error\n"); exit(1); } nitems = atoi(argv[1]); nproducers = min(atoi(argv[2]), maxthrs); //create 3 semaphore sem_init(&shared.mutex, 0, 1); sem_init(&shared.nempty, 0, nbuff); sem_init(&shared.nstored, 0, 0); for(i = 0; i < nproducers; ++i){ count[i] = 0; pthread_create(&tid_produce[i], null, produce, &count[i]); } pthread_create(&tid_consume, null, consume, null); for(i = 0; i < nproducers; ++i){ pthread_join(tid_produce[i], null); printf("count[%d] = %d\n", i, count[i]); } pthread_join(tid_consume, null); sem_destroy(&shared.mutex); sem_destroy(&shared.nempty); sem_destroy(&shared.nstored); exit(0); } void* produce(void *arg){ int i; for(i = 0; i < nitems; ++i){ sem_wait(&shared.nempty); sem_wait(&shared.mutex); if(shared.idx >= nitems){ sem_post(&shared.nempty);//注意点 sem_post(&shared.mutex); return null;// all done } shared.buff[shared.idx % nbuff] = shared.val; shared.idx++; shared.val++; sem_post(&shared.mutex); sem_post(&shared.nstored); *((int*) arg) += 1; } return null; } void* consume(void* args){ int i; for(i = 0; i < nitems; ++i){ sem_wait(&shared.nstored); sem_wait(&shared.mutex); if(shared.buff[i % nbuff] != i){ printf("error:buff[%d] = %d\n", i, shared.buff[i % nbuff]); } sem_post(&shared.mutex); sem_post(&shared.nempty); } return null; }
3,多个生产者和多个消费者
#include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <sys/stat.h> #include <semaphore.h> #define nbuff 10 #define maxthrs 100 #define min(x,y) ( x > y ? y:x ) int nitems, nproducers, nconsumers; struct { int buff[nbuff]; int idx; int val; int gidx; int gval; sem_t mutex, nempty, nstored; } shared; void* produce(void *args); void* consume(void* args); int main(int argc, char** argv){ int i, prodcount[maxthrs], conscount[maxthrs]; pthread_t tid_produce[maxthrs], tid_consume[maxthrs]; if(argc != 4){ printf("usage error\n"); exit(1); } nitems = atoi(argv[1]); nproducers = min(atoi(argv[2]), maxthrs); nconsumers = min(atoi(argv[3]), maxthrs); //create 3 semaphore sem_init(&shared.mutex, 0, 1); sem_init(&shared.nempty, 0, nbuff); sem_init(&shared.nstored, 0, 0); for(i = 0; i < nproducers; ++i){ prodcount[i] = 0; pthread_create(&tid_produce[i], null, produce, &prodcount[i]); } for(i = 0; i < nconsumers; ++i){ conscount[i] = 0; pthread_create(&tid_consume[i], null, consume, &conscount[i]); } for(i = 0; i < nproducers; ++i){ pthread_join(tid_produce[i], null); printf("prodcount[%d] = %d\n", i, prodcount[i]); } for(i = 0; i < nconsumers; ++i){ pthread_join(tid_consume[i], null); printf("conscount[%d] = %d\n", i, conscount[i]); } sem_destroy(&shared.mutex); sem_destroy(&shared.nempty); sem_destroy(&shared.nstored); exit(0); } void* produce(void *arg){ int i; for(i = 0; i < nitems; ++i){ sem_wait(&shared.nempty); sem_wait(&shared.mutex); if(shared.idx >= nitems){ sem_post(&shared.nstored);//注意点 sem_post(&shared.nempty);//注意点 sem_post(&shared.mutex); return null;// all done } shared.buff[shared.idx % nbuff] = shared.val; shared.idx++; shared.val++; sem_post(&shared.mutex); sem_post(&shared.nstored); *((int*) arg) += 1; } return null; } void* consume(void* arg){ int i; for(; ;){ sem_wait(&shared.nstored); sem_wait(&shared.mutex); if(shared.gidx >= nitems){ sem_post(&shared.nstored);//注意点 sem_post(&shared.mutex); return null;// all done } i = shared.gidx % nbuff; if(shared.buff[i] != shared.gval){ printf("error:buff[%d] = %d\n", i, shared.buff[i]); } shared.gidx++; shared.gval++; sem_post(&shared.mutex); sem_post(&shared.nempty); *((int*) arg) += 1; } return null; }
c/c++ 学习互助qq群:877684253
本人微信:xiaoshitou5854