操作系统上机编程2-----unixc实现进程同步
2017-06-10 20:07
260 查看
撰写时间:2017.6.10
通过信号量机制和条件变量机制实现进程同步
pc1.c: 使用条件变量解决生产者、计算者、消费者问题
系统中有3个线程:生产者、计算者、消费者
系统中有2个容量为4的缓冲区:buffer1、buffer2
生产者生产’a’、’b’、’c’、‘d’、’e’、’f’、’g’、’h’八个字符,放入到buffer1
计算者从buffer1取出字符,将小写字符转换为大写字符,放入到buffer2
消费者从buffer2取出字符,将其打印到屏幕上
pc2.c: 使用信号量解决生产者、计算者、消费者问题
功能和前面的实验相同,使用信号量解决
等待条件变量满足
通知条件变量满足
->最原始
说明:上述只是最简单的条件变量的实现方式.其中会造成的问题就是:如果程序中运行着多个线程1,那么在if语句判断结束之后,在wait函数执行之前.被中断,而在中断线程中改变条件,使得条件满足,再次切换到thread1中的时候,由于程序已经执行过判断条件.就会出现前后不一致的问题!所以我们需要增加一个互斥量,保护条件中涉及到的变量的安全,也就是保证线程安全!这也就是为什么条件变量要与互斥量共用的原因.
->修改1:
运行过程:thread1获得mutex锁->thread1判断条件不满足->thread1调用cond_wait函数(线程挂起+释放mutex锁)->thread2调用signal(唤醒所有的被该条件变量阻塞的进程)->执行结束.
虽然看起来好像已经可以啦,但是还有一个问题没有解决就是使用while还是if的问题.关于这个问题.可以参考下面这篇博客
->修改2
通过信号量机制和条件变量机制实现进程同步
pc1.c: 使用条件变量解决生产者、计算者、消费者问题
系统中有3个线程:生产者、计算者、消费者
系统中有2个容量为4的缓冲区:buffer1、buffer2
生产者生产’a’、’b’、’c’、‘d’、’e’、’f’、’g’、’h’八个字符,放入到buffer1
计算者从buffer1取出字符,将小写字符转换为大写字符,放入到buffer2
消费者从buffer2取出字符,将其打印到屏幕上
pc2.c: 使用信号量解决生产者、计算者、消费者问题
功能和前面的实验相同,使用信号量解决
条件变量
1.api
初始化条件变量#include<pthread.h> int pthread_cond_init(pthread_cond_t*cond,const pthread_condattr_t* attr); int pthread_cond_destory(pthread_cond_t*cond);
等待条件变量满足
#include<pthread.h> int pthread_cond_wait(pthread_cond_t* cond,pthread_mutex_t* mutex);
通知条件变量满足
#include<pthread.h> int pthread_cond_signal(pthread_cond_t* cond);
2.使用
注:所谓的条件变量并没有控制所谓的条件,一般需要我们在外围增加判断条件.所以,条件变量一般的使用方式是:->最原始
///////#thread1 if(条件不满足){ pthread_cond_wait(&cond,&mutex); } /////#thread2 pthread_cond_signal(&cond)
说明:上述只是最简单的条件变量的实现方式.其中会造成的问题就是:如果程序中运行着多个线程1,那么在if语句判断结束之后,在wait函数执行之前.被中断,而在中断线程中改变条件,使得条件满足,再次切换到thread1中的时候,由于程序已经执行过判断条件.就会出现前后不一致的问题!所以我们需要增加一个互斥量,保护条件中涉及到的变量的安全,也就是保证线程安全!这也就是为什么条件变量要与互斥量共用的原因.
->修改1:
pthread_mutex_t mutex; pthread_cond_t cond; ////#thread1 pthread_mutex_lock(&mutex); if(条件不满足){ pthread_cond_wait(&cond,&mutex); } pthread_mutex_unlock(&mutex); /////#thread2 pthread_cond_signal(&cond)
运行过程:thread1获得mutex锁->thread1判断条件不满足->thread1调用cond_wait函数(线程挂起+释放mutex锁)->thread2调用signal(唤醒所有的被该条件变量阻塞的进程)->执行结束.
虽然看起来好像已经可以啦,但是还有一个问题没有解决就是使用while还是if的问题.关于这个问题.可以参考下面这篇博客
->修改2
pthread_mutex_t mutex; pthread_cond_t cond; ////#thread1 pthread_mutex_lock(&mutex); while(条件不满足){ pthread_cond_wait(&cond,&mutex); } pthread_mutex_unlock(&mutex); /////#thread2 pthread_cond_signal(&cond)
pc1.c: 使用条件变量解决生产者、计算者、消费者问题
#include<stdio.h> #include<pthread.h> //#include<semaphore.h> //变量储存区 char buff1[5]; char buff2[5]; int index_buff1 = 0; int index_buff2 = 0; pthread_mutex_t buff1_mutex; pthread_mutex_t buff2_mutex; pthread_cond_t buff1_empty_cond; pthread_cond_t buff1_full_cond; pthread_cond_t buff2_empty_cond; pthread_cond_t buff2_full_cond; void init_mutex(){ pthread_mutex_init(&buff1_mutex,NULL); pthread_mutex_init(&buff2_mutex,NULL); pthread_cond_init(&buff1_empty_cond,NULL); pthread_cond_init(&buff1_full_cond,NULL); pthread_cond_init(&buff2_empty_cond,NULL); pthread_cond_init(&buff2_full_cond,NULL); } void destory_mutex(){ pthread_mutex_destroy(&buff1_mutex); pthread_mutex_destroy(&buff2_mutex); pthread_cond_destroy(&buff1_empty_cond); pthread_cond_destroy(&buff1_full_cond); pthread_cond_destroy(&buff2_empty_cond); pthread_cond_destroy(&buff2_full_cond); } void *producer(void *arg){ int index; for(index=0;index<8;index++){ pthread_mutex_lock(&buff1_mutex); while(index_buff1>=4){ pthread_cond_wait(&buff1_empty_cond,&buff1_mutex); } buff1[index_buff1] = index+'a'; printf("1--------\n"); index_buff1++; pthread_cond_signal(&buff1_full_cond); pthread_mutex_unlock(&buff1_mutex); } return (void*)0; } void *lowToUp(void *arg){ int index; for(index=0;index<8;index++){ pthread_mutex_lock(&buff1_mutex); pthread_mutex_lock(&buff2_mutex); while(index_buff1<1){ pthread_cond_wait(&buff1_full_cond,&buff1_mutex); } while(index_buff2>=4){ pthread_cond_wait(&buff2_empty_cond,&buff2_mutex); } printf("2--------\n"); index_buff1--; buff2[index_buff2] = buff1[index_buff1]-32; index_buff2++; pthread_cond_signal(&buff1_empty_cond); pthread_cond_signal(&buff2_full_cond); pthread_mutex_unlock(&buff2_mutex); pthread_mutex_unlock(&buff1_mutex); } return (void*)0; } void *consume(void *arg){ int index; for(index=0;index<8;index++){ pthread_mutex_lock(&buff2_mutex); while(index_buff2<1){ pthread_cond_wait(&buff2_full_cond,&buff2_mutex); } index_buff2--; printf("3--------%c\n",buff2[index_buff2]); pthread_cond_signal(&buff2_empty_cond); pthread_mutex_unlock(&buff2_mutex); } return (void*)0; } int main(){ init_mutex(); pthread_t produce_thread; pthread_t calc_thread; pthread_t consume_thread; pthread_create(&produce_thread,NULL,producer,NULL); pthread_create(&calc_thread,NULL,lowToUp,NULL); pthread_create(&consume_thread,NULL,consume,NULL); pthread_join(produce_thread,NULL); pthread_join(calc_thread,NULL); pthread_join(consume_thread,NULL); destory_mutex(); return 0; }
信号量
信号量机制就是传统的pv操作.当资源不足的时候等待,当资源充足的时候,等待系统的线程调度.不存在上述条件变量所谓的通知.下面直接贴代码,很简单.#include<stdio.h> #include<sys/types.h> #include<sys/ipc.h> #include<pthread.h> #include<semaphore.h> //储存变量 char buff1[5]; char buff2[5]; int index_buff1 = 0; int index_buff2 = 0; //定义两个buff的互斥信号量 sem_t buff1_mutex; sem_t buff2_mutex; //定义进程内的互斥信号量 sem_t buff1_full; sem_t buff1_empty; sem_t buff2_full; sem_t buff2_empty; void init_mutex(){ sem_init(&buff1_mutex,0,1); sem_init(&buff2_mutex,0,1); sem_init(&buff1_full,0,0); sem_init(&buff1_empty,0,4); sem_init(&buff2_full,0,0); sem_init(&buff2_empty,0,4); } void destroy_mutex(){ sem_destroy(&buff1_mutex); sem_destroy(&buff2_mutex); sem_destroy(&buff1_full); sem_destroy(&buff1_empty); sem_destroy(&buff2_full); sem_destroy(&buff2_empty); } void *producer(void *arg){ printf("hello world\n"); int index; for(index=0;index<8;index++){ //printf("%d\n",index); sem_wait(&buff1_empty); sem_wait(&buff1_mutex); buff1[index_buff1] = index+'a'; //printf("%c\n",buff1[index_buff1]); //printf("1--------%c--%d\n",buff1[index_buff1],index_buff1); //index_buff2--; index_buff1++; sem_post(&buff1_mutex); sem_post(&buff1_full); } return (void*)0; } void *lowToUp(void *arg){ int index; for(index=0;index<8;index++){ sem_wait(&buff1_full); sem_wait(&buff2_empty); sem_wait(&buff1_mutex); sem_wait(&buff2_mutex); index_buff1--; buff2[index_buff2] = buff1[index_buff1]-32; //printf("2-------%c--%d\n",buff2[index_buff2],index_buff2); index_buff2++; sem_post(&buff2_mutex); sem_post(&buff1_mutex); sem_post(&buff2_full); sem_post(&buff1_empty); } return (void*)0; } void *consume(void *arg){ int index; for(index=0;index<8;index++){ sem_wait(&buff2_full); sem_wait(&buff2_mutex); index_buff2--; printf("3--------%c \n",buff2[index_buff2]); sem_post(&buff2_mutex); sem_post(&buff2_empty); } return (void*)0; } int main(){ pthread_t produce_thread; pthread_t calc_thread; pthread_t consume_thread; printf("hello wrold"); //初始化所有的信号量 init_mutex(); printf("hello wrold\n"); pthread_create(&produce_thread,NULL,producer,NULL); pthread_create(&calc_thread,NULL,lowToUp,NULL); pthread_create(&consume_thread,NULL,consume,NULL); pthread_join(produce_thread,NULL); pthread_join(calc_thread,NULL); pthread_join(consume_thread,NULL); destroy_mutex(); return 0; }
相关文章推荐
- UNIX环境高级编程学习之第十章信号-用信号实现父子进程同步
- UNIX环境高级编程学习之第十五章进程间通信 - 通过匿名管道实现父子进程同步
- 采用用同步编程的方式实现跨进程异步获取数据[一]
- 【UNIX环境编程、操作系统】孤儿进程和僵尸进程
- UNIX环境高级编程学习之第十五章进程间通信 - 两个进程通过映射普通文件实现共享内存通信
- UNIX环境高级编程学习之第十五章进程间通信 - 通过半双工匿名管道实现父子进程通信
- Unix环境高级编程——守护进程记录总结(从基础到实现)
- 采用用同步编程的方式实现跨进程异步获取数据[二]-创建玩家账号和获取角色列表
- 【操作系统】进程(线程)间同步互斥问题——高校上机实习问题
- UNIX环境高级编程学习之第八章进程控制-用父子进程实现打开kate,返回kate关闭状态
- 采用用同步编程的方式实现跨进程异步获取数据
- UNIX编程的操作系统基础知识(进程篇)
- 进程、线程、文件共享--操作系统概念--unix环境高级编程
- Unix高级编程:进程的同步、加载新的程序映像、环境变量
- 进程编程3 - UNIX高级环境编程第9章读书笔记
- 进程编程1 – Unix环境高级编程7章读书笔记
- 使用临界段实现优化的进程间同步对象-原理和实现
- 使用临界段实现优化的进程间同步对象-原理和实现
- 进程编程1 – Unix环境高级编程7章读书笔记
- 进程编程1 – Unix环境高级编程7章读书笔记