操作系统实验三:同步问题

实验目的

  1. 系统调用的进一步理解。
  2. 进程上下文切换。
  3. 同步的方法。

实验题目

1. 通过fork的方式,产生4个进程P1,P2,P3,P4,每个进程打印输出自己的名字,例如P1输出“I am the process P1”。要求P1最先执行,P2、P3互斥执行,P4最后执行。通过多次测试验证实现是否正确

分析:

    首先使用fork产生P1进程,之后产生P2、P3进程,此时需要在P2和P3之间加互斥锁,P2和P3互斥访问临界资源并执行,随后当P2或P3至少一个进程完成时,执行fork产生P4进程。 

互斥变量使用数据类型:pthread_mutex_t,使用互斥量前要先初始化,使用的函数如下:

#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

然后使用pthread_mutex_lock(&mutex) 和 pthread_mutex_unlock(&mutex) 分别为进程上锁和解锁,从而实现互斥操作。

 程序代码编写如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(){
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL);

pid_t pid1 = fork();
if(pid1 == 0){
	printf("I'm the process P1.\n");
	return 0;
	}

waitpid(pid1, NULL, 0);
pid_t pid2 = fork();
if(pid2 == 0){
	pthread_mutex_lock(&mutex);
	printf("I'm the process P2.\n");
	pthread_mutex_unlock(&mutex);
	return 0;
	}

waitpid(pid1, NULL, 0);
pid_t pid3 = fork();
if(pid3 == 0){
	pthread_mutex_lock(&mutex);
	printf("I'm the process P3.\n");
	pthread_mutex_unlock(&mutex);
	return 0;
	}

int pr2 = waitpid(pid2, NULL, 0);
int pr3 = waitpid(pid3, NULL, 0);
pid_t pid4 = fork();
if(pid4 == 0 && (pr2 == pid2 || pr3 == pid3)){ /*P2和P3有一个完成即可进行P4*/
	printf("I'm the process P4.\n");
	return 0;
	}

else if(pid1 != -1){
	waitpid(pid1, NULL, 0);
	waitpid(pid2, NULL, 0);
	waitpid(pid3, NULL, 0);
	waitpid(pid4, NULL, 0);
	}

pthread_mutex_destroy(&mutex);

return 0;
}

编译执行,程序运行结果如下图所示,执行顺序为P1、P2、P3、P4

为了看出P2和P3互斥运行的关系,之后在P2线程内加入睡眠1s

if(pid3 == 0){
	sleep(1);   //新加
	pthread_mutex_lock(&mutex);
	printf("I'm the process P3.\n");
	pthread_mutex_unlock(&mutex);
	return 0;
	}

运行结果如下,执行顺序变为P1、P2、P3、P4

可以发现P2和P3的顺序是不确定的,某一个运行之后才会运行另一个。 

  

2. 火车票余票数ticketCount 初始值为1000,有一个售票线程,一个退票线程,各循环执行多次。添加同步机制,使得结果始终正确。要求多次测试添加同步机制前后的实验效果。

分析:同步机制就是设置两个信号量,分别是product和consume, 分别用来表示buf缓存区中空闲单元的个数和buf缓存区中非空闲单元的个数,并初始化consume信号量个数为1000。每次售票前都检测非空闲单元数是否大于0,成功售出一张票之后将product信号量增一,同时将ticketCount减一;退票前检测空闲单元数是否大于0,成功退票后consume信号量增一,同时ticketCount加一。 

不含同步机制的代码编写如下:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

int ticketCount = 1000;
int temp;

void *sale(void *arg) {
	for (int i = 0; i < 1050; i++){
		temp = ticketCount;
		pthread_yield();
		temp = temp - 1;
		pthread_yield();
		ticketCount = temp;
		printf("sale: %d ticketCount: %d ",i, ticketCount);
	}
	return NULL;
}

void *refund(void *arg) {

	for (int i = 0; i < 1050; i++){
		temp = ticketCount;
		pthread_yield();
		temp = temp + 1;
		pthrea
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值