一.信号量(semaphore)
mutex变量是非0即1的,可看作一种资源的可用数量,初始化时mutex是1,表示有一个可用资源,加锁时获得该资源,将mutex减到0,表示不再有可用资源,解锁时释放该资源,将mutex重新加到1,表示又有了一个可用资源。
semaphore和mutex类似,表示可用资源的数量,和mutex不同的是这个数量可以大于1。
也就是说,当信号量描述的资源数目是1时,此时的信号量和互斥锁相同。
下面所讲的是POSIX semaphore库函数,这种信号不仅可用于同一进程的线程间同步,也可用于不同进程间的同步。
所用的函数如下:
#include<semaphore.h>
int sem_init(sem_t *sem,int pshared,unsigned int value);
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_destroy(sem_t *sem);
semaphore变量的类型是sem_t,sem_init()初始化一个semaphore变量,value参数表示可用资源的数量,pshared参数为0表示信号量用于同一进程的线程同步。
调用sem_wait()可以获得资源(P操作),使semaphore的值减1,如果调用sem_wait()时semaphore的值已经是0,则挂起等待;如果不希望挂起等待,可以调用sem_try_wait();调用sem_post()可以释放资源(V操作),使semaphore得值加1,同时唤醒挂起等待的线程。
二.基于固定大小的环形队列来实现生产者消费者模型
1 #include<stdio.h> 2 #include<semaphore.h> 3 #include<pthread.h> 4 #define _SIZE_ 20 5 sem_t blank; 6 sem_t data; 7 pthread_mutex_t lock1; 8 pthread_mutex_t lock2; 9 int buf[_SIZE_]; 10 void *product(void *arg) 11 { 12 int i=0; 13 int count=0; 14 while(1) 15 { 16 //pthread_mutex_lock(&lock1); //把生产者之间的锁加在信号量外面(不可取) 17 sem_wait(&blank); 18 pthread_mutex_lock(&lock1); //把生产者之间的锁加在信号量的里面(可取) 19 buf[i]=count++; 20 sleep(rand()%3); 21 pthread_mutex_unlock(&lock1); 22 sem_post(&data); 23 i++; 24 i%=_SIZE_; 25 //pthread_mutex_unlock(&lock1); 26 } 27 } 28 void *consumer(void *arg) 29 { 30 int i=0; 31 int count=0; 32 while(1) 33 { 34 //pthread_mutex_lock(&lock2); //把消费者之间的锁加在信号量的外面(不可取) 35 sem_wait(&data); 36 pthread_mutex_lock(&lock2); //把消费者之间的锁加在信号量的里面(可取) 37 count=buf[i]; 38 printf("consumer:%d,consumer data:%d\n",(int)arg,count); 39 pthread_mutex_unlock(&lock2); 40 sem_post(&blank); 41 i++; 42 i%=_SIZE_; 43 //pthread_mutex_unlock(&lock2); 44 } 45 } 46 int main() 47 { 48 pthread_mutex_init(&lock1,NULL); 49 pthread_mutex_init(&lock2,NULL); 50 pthread_t tid1,tid2,tid3,tid4; 51 sem_init(&blank,0,_SIZE_); 52 sem_init(&data,0,0); 53 pthread_create(&tid1,NULL,product,(void*)1); 54 pthread_create(&tid2,NULL,product,(void*)2); 55 pthread_create(&tid3,NULL,consumer,(void*)3); 56 pthread_create(&tid4,NULL,consumer,(void*)4); 57 pthread_join(tid1,NULL); 58 pthread_join(tid2,NULL); 59 pthread_join(tid3,NULL); 60 pthread_join(tid4,NULL); 61 pthread_mutex_destroy(&lock1); 62 pthread_mutex_destroy(&lock2); 63 sem_destroy(&blank); 64 sem_destroy(&data); 65 return 0; 66 }
运行结果:(1)把锁加在信号量的内部:
(2)把锁加在信号量的外部