关于信号量,我们在前面进程间通信也谈到过,今天我们再来看看使用信号量实现线程间的同步与互斥问题。
再来说说什么是信号量?
信号量的使用主要用来保护共享资源,使该资源在一个时刻只有一个进程(线程)所拥有。在线程中的semaphore变量的类型为sem_t。我们先来了解一下信
号量的操作函数。
sem_init()用来初始化一个信号量,sem_t *sem是自己定义的sem变量的地址,pshared参数为0,用于表示信号量用于同一进程间的线程间同步,value参
数表示可用资源的数量。
sem_wait()可以获得资源,即指P操作,使信号量的值减1,如果调用此函数时semaphore的值已经是0,则该线程就挂起等待。
sem_trywait()在申请资源不成功时不会使线程挂起等待。我们一般不使用sem_timewait(),该函数设置了自己的等待时间。
sem_post()函数可以释放资源,即指V操作,使信号量的值加1,同时唤醒挂起等待的线程。参数就是自己定义的信号量的地址。
可见,线程间的PV操作与进程间的PV操作不一样,进程间是通过semop()来进行操作的。
sem_destroy()函数是用来销毁信号量的。参数同样是sem_t sem的地址。
我们上一节用的是条件变量来实现了消费者——生产者模型,生产者通过往单链表的头部放数据,消费者每次从链表的头部来读取数据来实现同步与互
斥,链表为空时就让消费者去wait,当有数据可以消费时,生产者就去signal消费者。这节我们用信号量再次来模拟实现一次消费者——生产者模型,这次二者
的交易场所变成了环形buffer,这个环形场所我们用一维数组来实现。
来看看实现的代码:
我们在该代码中应该保证生产者先运行,其次需要注意的是:生产者生产数据,会让数据增多而剩余空间减小,消费者消费数据,会让数据减少而剩余空
间增多。初始化信号量时,生产者的初始可用资源的数组的SIZE,而消费者初始可用资源是0。
来看看结果,第一种是生产者每次生产完,消费只进行消费,消费者消费完生产者进行生产。
第二种是生产者生产一个,消费者就去消费一个。
|