在上一篇文章中,利用信号量实现了线程间的互斥,这一篇将要利用信号量的互斥同步机制来实现一个经典实例,就是“生产者和消费者”。
1、简单描述生产者和消费者的问题。
有一个缓冲区和两个线程:生产者和消费者。生产者把产品放入缓冲区,而消费者从缓冲区中拿走。当缓冲区满时,生产者必须等待;另外,当缓冲区空时,消费者必须等待,并且缓冲区不能同时进行生产者和消费者的操作。
- #include <stdio.h>
- #include <stdlib.h>
- #include <pthread.h>
- #include <semaphore.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <string.h>
- #define FIFO "my_fifo"
- #define N 10
- #define return_if_fail(p) if((p) == 0){printf ("[%s]:func error!/n", __func__);return;}
- typedef struct _PrivInfo
- {
- sem_t avail;
- sem_t full;
- sem_t mutex;
- char buf_r[255];
- time_t end_time;
- int fd;
- }PrivInfo;
- static void info_init (PrivInfo* thiz);
- static void info_destroy (PrivInfo* thiz);
- static void* productor (PrivInfo* thiz);
- static void* consumer (PrivInfo* thiz);
- int main (int argc, char* argv[])
- {
- pthread_t pt_1 = 0;
- pthread_t pt_2 = 0;
- int ret = 0;
- PrivInfo* thiz = NULL;
- thiz = (PrivInfo*) malloc (sizeof (PrivInfo));
- if (thiz == NULL)
- {
- printf ("[%s]: Failed to malloc PrivInfo./n", __func__);
- return -1;
- }
- info_init (thiz);
- ret = pthread_create (&pt_1, NULL, (void*)productor, thiz);
- if (ret != 0)
- {
- perror ("pthread_1_create:");
- }
- ret = pthread_create (&pt_2, NULL, (void*)consumer, thiz);
- if (ret != 0)
- {
- perror ("pthread_2_func:");
- }
- pthread_join (pt_1, NULL);
- pthread_join (pt_2, NULL);
- info_destroy (thiz);
- thiz = NULL;
- return 0;
- }
- static void info_init (PrivInfo* thiz)
- {
- return_if_fail (thiz != NULL);
- thiz->end_time = time(NULL) + 10;
- sem_init (&thiz->avail, 0, N);
- sem_init (&thiz->full, 0, 0);
- sem_init (&thiz->mutex, 0, 1);
- if (mkfifo (FIFO, O_CREAT|O_EXCL) && (errno != EEXIST))
- {
- printf ("cannot create fifo server./n");
- }
- printf ("Prepareing for reading bytes.../n");
- memset (thiz->buf_r, 0, sizeof (thiz->buf_r));
- thiz->fd = open (FIFO, O_RDWR|O_NONBLOCK, 0777);
- if (thiz->fd == -1)
- {
- perror ("open FIFO:");
- info_destroy (thiz);
- exit (1);
- }
- return ;
- }
- static void info_destroy (PrivInfo* thiz)
- {
- return_if_fail (thiz != NULL);
- sem_destroy (&thiz->avail);
- sem_destroy (&thiz->full);
- sem_destroy (&thiz->mutex);
- free (thiz);
- thiz = NULL;
- return;
- }
- static void* productor (PrivInfo* thiz)
- {
- return_if_fail (thiz != NULL);
- int ret = 0;
- while (time (NULL) < thiz->end_time)
- {
- sem_wait (&thiz->avail);
- sem_wait (&thiz->mutex);
- if ((ret = write (thiz->fd, "hello", 5)) == -1)
- {
- if (errno == EAGAIN)
- {
- printf ("The FIFO has not been read, Please try later again./n");
- }
- else
- {
- printf ("write hello to the FIFO./n");
- }
- }
- sem_post (&thiz->full);
- sem_post (&thiz->mutex);
- sleep (1);
- }
- return;
- }
- static void* consumer (PrivInfo* thiz)
- {
- return_if_fail (thiz != NULL);
- int ret = 0;
- while (time (NULL) < thiz->end_time)
- {
- sem_wait (&thiz->full);
- sem_wait (&thiz->mutex);
- if ((ret = read(thiz->fd, thiz->buf_r, 255)) > 0)
- {
- printf ("read %s frm FIFO./n", thiz->buf_r);
- }
- else
- {
- if (errno == EAGAIN)
- {
- printf ("no data yet./n");
- }
- }
- sem_post (&thiz->avail);
- sem_post (&thiz->mutex);
- sleep(1);
- }
- return;
- }
从上面的经典例子中,结合了多线程的同时性编程问题。学习线程算是告了一段落,在以后的编程应用中,希望能落实到实践中去,大家一起加油~~