Linux同步互斥(Peterson算法,生产者消费者模型)
-
同步
两个或两个以上随时间变化的量在变化过程中保持一定的相对关系。
-
互斥
对一组并发进程,一次只有一个进程能够访问一个给定的资源或执行一个给定的功能。
互斥技术可以用于解决诸如资源争用之类的冲突,还可以用于进程间的同步,使得它们可以合作。典型例子便是生产者/消费者模型。
- 同步互斥的实现思路主要有两种:
- 软件方法(这里讲的)
- 信号量
-
使用POSIX线程库(pthread_),来创建线程,管理线程,实现同步互斥。
-
POSIX(可移植操作系统)线程是线程的POSIX标准,定义了创建和操作线程的一套API。
-
可用于多线程编程
-
POSIX线程库函数—介绍将会用到的
-
int pthread_create(pthread_t *thread, pthread_attr_t *attr,void *(*start_routine)(void *), void *arg);
•作用:创建一个线程
•参数thread:如果创建线程成功,标识本线程的唯一标识符通过本变量返回给函数调用者;
•参数attr:调用者通过该参数描述期望创建的线程具有什么样的属性,传入NULL表示使用默认属性;
•参数start_routine:线程的运行实体;
•参数arg:传递给线程实体的参数;
•返回值:0成功,非0为错误码;
- int pthread_join(pthread_t th, void **thread_return);
•作用:等待一个线程结束,以阻塞的方式等待th指定的线程结束。
•参数th:描述等待一个线程结束,其取值为pthread_create函数第一个参数的返回值;
•参数thread_return:被等待线程结束时的返回值,用户定义的指针,用来存储被等待线程的返回值。
-
Peterson算法
-
Peterson算法是一个实现互斥的并发程序设计算法
-
临界缓冲区问题描述
有一个或者多个生产者产生某种类型的数据(记录、字符),并放置在缓冲区中;有一个消费者从缓冲区中取数据,每次取一项;系统保证避免对缓冲区的重复操作,也就是说,在任何时候只有一个代理(生产者或者消费者)可以访问缓冲区。
- 生产者消费者模型(C代码)
-
//thread.c
1 #include <stdio.h> 2 #include <pthread.h> 3 #define MAX 10 //需要生产的数量 4 pthread_mutex_t the_mutex; //互斥锁 5 pthread_cond_t condc, condp; //条件变量 6 int buffer = 0;//生产者、消费者使用的缓冲区 7 8 void *producer(void *ptr) 9 { 10 int i; 11 for(i=1; i<=10; i++) 12 { 13 pthread_mutex_lock(&the_mutex); //互斥使用缓冲区 14 while(buffer !=0) pthread_cond_wait(&condp, &the_mutex); //阻塞等待 15 printf("procucer produce item %d\n",i); 16 buffer = i; //生产产品 17 pthread_cond_signal(&condc);//通知消费者消费 18 pthread_mutex_unlock(&the_mutex);//释放缓冲区 19 } 20 21 pthread_exit(0); 22 23 } 24 25 void *consumer(void *ptr) 26 { 27 28 int i; 29 for(i=1; i<=10; i++) 30 { 31 pthread_mutex_lock(&the_mutex);//互斥使用缓冲区 32 while(buffer ==0) pthread_cond_wait(&condc, &the_mutex); //阻塞等待 33 printf("consumer consume item %d\n",i); 34 buffer = 0;//清空缓存区 35 pthread_cond_signal(&condp);//通知生产者生产产品 36 pthread_mutex_unlock(&the_mutex);//释放缓冲区 37 } 38 pthread_exit(0); 39 40 } 41 42 int main(int argc, char *argv[]) 43 { 44 pthread_t pro, con; 45 46 pthread_mutex_init(&the_mutex, 0); //创建互斥锁 47 pthread_cond_init(&condc,0); //初始化条件变量 48 pthread_cond_init(&condp,0); 49 50 pthread_create(&con, 0, consumer, 0); 51 pthread_create(&pro, 0, producer, 0); 52 pthread_join(pro,0); 53 pthread_join(con,0); 54 pthread_cond_destroy(&condc); 55 pthread_cond_destroy(&condp); 56 pthread_mutex_destroy(&the_mutex); 57 return 0; 58 }输出:
-
procucer produce item 1 consumer consume item 1 procucer produce item 2 consumer consume item 2 procucer produce item 3 consumer consume item 3 procucer produce item 4 consumer consume item 4 procucer produce item 5 consumer consume item 5 procucer produce item 6 consumer consume item 6 procucer produce item 7 consumer consume item 7 procucer produce item 8 consumer consume item 8 procucer produce item 9 consumer consume item 9 procucer produce item 10 consumer consume item 10
注意:
-
在编译中要加 -lpthread参数, 如:gcc thread.c -o thread –lpthread
- 使用到的一些函数功能介绍
-
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
作用:互斥的条件等待,阻塞线程
参数:*cond是指向一个条件变量的指针
*mutex则是对相关的互斥锁的指针
-
int pthread_cond_signal(pthread_cond_t *cond)
作用:发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状态,继续执行
参数:*cond是指向一个条件变量的指针