一.信号量(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)把锁加在信号量的内部:

    wKiom1ccka-AsRS3AACGcrHB5kc740.png

    (2)把锁加在信号量的外部

    wKiom1ccur6zUYmdAABuBzGZg1M919.png