进程同步
pv 操作 互斥锁
1
2
3
4P --wait(信号量S){
S<=0
S-- //上锁
}成对出现
1
2
3V --signal(信号量){
S++ //开锁
}生产者
1 | int in(),out=(); |
- 消费者
1 | void consumer(){ |
1 | void main(){ |
第1关:生产者消费者同步控制
任务描述
本关任务:编写生产者消费者同步控制程序。
相关知识
为了完成本关任务,你需要掌握:1.理解生产者消费者同步问题,2.线程的编写方法,3.使用信号量实现线程间同步控制。
线程并发引起的同步问题
线程以并发形式运行,当并发的线程间访问共享数据时,会发后争用现象,不进行同步控制的线程运行会造成不恰当的结果。
生产者消费者同步问题
生产者消费者是典型的同步问题,他们共享了一个缓冲池(全局变量数组),当缓冲池有空位时生产者线程向缓冲池中依次赋值,如果缓冲池满则等待。当缓冲池中有数据时消费者线程从中取走数据,如果缓冲池空则等待。
如何解决线程间访问共享变量的冲突问题
当多个线程访问同一个共享变量时,共享变量成为临界资源,它需要操作系统提供同步控制机制,以保证多个线程可以依序访问,当一个线程操作临界资源时其它线程不会中断其操作,因此对临界资源的操作是安全的。 下面是linux平台使用信号量的头文件和方法。 #include <semaphore.h> int sem_init(sem_t * sem, int pshared, unsigned int value);//创建信号量变量,value是信号量的初值 int sem_destroy(sem_t *sem);//销毁信号量 int sem_post(sem_t * sem); //信号量值增加1,并激活处于等待状态的线程 int sem_wait(sem_t * sem); //信号量值减少1 为0时将调用该方法的线程被OS阻塞
编程要求
主线程序启动生产者线程和消费者线程,并等待两个线程的结束。 两个线程使用三个信号量,其中生产者线程向全局变量进行十次赋值(代表生产),每次赋值前都要检查是否有空位,有空位的情况下 需要获得互斥量sem_mutex,并对共享缓冲区进行赋值,然后释放互斥量以便消费者线程可以操作缓冲区临界资源。 消费者线程要从缓冲区取值,取值前先检查是否有可用数据,有可用数据的情况下再获得互斥量sem_mutex,再取出缓冲区的值。 要特别说明的是生产者和消费者线程工作的速率是不同的,但在同步信号控制下,两个线程节奏互相配合步调一致。在《计算机操作系统》 教材中使用了伪代码,并且循环体没有结束条件,在此用C语言改写原程序,生产者一共只生产十个数据。 ####测试说明 为简化数据操作,程序没有输入,主线程已经写好, void * producer(void * arg); void * consumer(void * arg); static sem_t sem_empty;//空位个数 static sem_t sem_full; //可用数据个数 static sem_t sem_mutex; //互斥量,用于控制两个线程互斥访问缓冲区 static int buffer[]={0,0,0}; int main(int argc,char * argv[]) { pthread_t id_prod,id_consum; sem_init(&sem_empty,0,3); //初值为3,空位为3, sem_init(&sem_full,0,0); //初值为0,可用数据个数为0, sem_init(&sem_mutex,0,1); //初值为1,用于控制两个线程互斥访问缓冲区 pthread_create(&id_prod, NULL,producer,NULL);//创建生产者线程 pthread_create(&id_consum,NULL,consumer,NULL);//创建消费者线程
pthread_join(id_prod,NULL); //主线程等待生产者线程结束 pthread_join(id_consum,NULL);//主线程等待消费者线程结束 sem_destroy(&sem_empty); sem_destroy(&sem_full); sem_destroy(&sem_mutex); return 0; } 学生需要补充producer线程与consumer中关于同步控制部分的程序。
输出:1至10 (需由学生根据程序生成正确结果) 开始你的任务吧,祝你成功!
1 | //stu001.c 生产者消费者同步控制,由学生完成缺失代码。 |
参考Linux下c++的东西
https://man7.org/linux/man-pages/man3/sem_wait.3.html
1 | sem_wait是一个函数,也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,将信号量的值将减到1。 |
1 | sem_post是给信号量的值加上一个“1”,它是一个“原子操作”---即同时对同一个信号量做加“1”操作的两个线程是不会冲突的;而同 时对同一个文件进行读和写操作的两个程序就有可能会引起冲突。 |
1 | sem_t C语言中,信号量的数据类型为结构sem_t,它本质上是一个长整型的数。 |
https://blog.51cto.com/u_13999641/4314815
没看完【argc,argv是什么】
真的忘的差不多了0.0