2024/02/02

本文详细介绍了C语言中互斥锁、无名信号量、条件变量以及无名和有名管道的实现,并通过示例展示了它们在并发编程中的使用,以及如何通过多进程实现进程间的通信。
摘要由CSDN通过智能技术生成

1> 将互斥机制的代码实现重新敲一遍

#include<myhead.h>
int num = 520;
//创建一个互斥锁变量
pthread_mutex_t mutex;

//定义任务1函数
void *task1(void *arg)
{
	printf("11111111111111111\n");

	//获取锁资源
	pthread_mutex_lock(&mutex);
	num=1314;
	sleep(3);
	printf("task1:num = %d\n",num);
	//释放锁资源
	pthread_mutex_unlock(&mutex);
}

//定义任务2函数
void *task2(void *arg)
{
	printf("22222222222222222\n");
	//获取锁资源
	pthread_mutex_lock(&mutex);
	num++;
	sleep(1);
	printf("task2:num = %d\n",num);
	//释放锁资源
	pthread_mutex_unlock(&mutex);
}

int main(int argc, const char *argv[])
{
	//初始化互斥锁
	pthread_mutex_init(&mutex,NULL);
	//创建两个线程
	pthread_t tid1,tid2;
	if(pthread_create(&tid1,NULL,task1,NULL)!=0)
	{
		printf("tid1 create error\n");
		return 0;
	}
	if(pthread_create(&tid2,NULL,task2,NULL)!=0)
	{
		printf("tid2 create error\n");
		return 0;
	}
	printf("tid1=%#lx,tid2=%#lx\n",tid1,tid2);

	//回收线程资源
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	
	//销毁互斥锁资源
	pthread_mutex_destroy(&mutex);
	
	return 0;
}

2> 将无名信号量的代码实现重新敲一遍

#include<myhead.h>

//1创建无名信号量
sem_t sem;

//定义生产者线程
void *task1(void *arg)
{
	int num = 5;
	while(num--)
	{
		sleep(1);

		printf("我生产了一辆3.0T 510马力的L6双涡轮增压发动机的宝马 M4\n");

		//4释放资源
		sem_post(&sem);
	}
	//退出线程
	pthread_exit(NULL);
}

//定义消费者线程
void *task2(void *arg)
{
	int num = 5;
	while(num--)
	{
		//3申请资源
		sem_wait(&sem);

		printf("我消费了一辆3.0T 510马力的L6双涡轮增压发动机的宝马 M4\n");
	}
	//退出线程
	pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
	//创建两个线程,分别是生产者和消费者
	pthread_t tid1,tid2;
	if(pthread_create(&tid1,NULL,task1,NULL)!=0)
	{
		printf("tid1 create error\n");
		return 0;
	}
	if(pthread_create(&tid2,NULL,task2,NULL)!=0)
	{
		printf("tid2 create error\n");
		return 0;
	}
	printf("tid1=%#lx,tid2=%#lx\n",tid1,tid2);

	//回收线程资源
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);

	//释放无名信号量
	sem_destroy(&sem);

	return 0;
}

3> 将条件变量的代码实现重新敲一遍

#include<myhead.h>

//1定义条件变量
pthread_cond_t cond;

//定义互斥锁变量
pthread_mutex_t mutex;

//定义生产者线程
void *task1(void *arg)
{
	int num = 5;
	while(num--)
	{
		sleep(1);

	printf("%#lx:\n我生产了一辆3.0T 510马力的L6双涡轮增压发动机的宝马 M4\n",pthread_self());
		//3唤醒一个消费者
//		pthread_cond_signal(&cond);
	}
	//唤醒所有等待线程
	pthread_cond_broadcast(&cond);
	//退出线程
	pthread_exit(NULL);
}

//定义消费者线程
void *task2(void *arg)
{
	//上锁
	pthread_mutex_lock(&mutex);
	//进入等待队列
	pthread_cond_wait(&cond,&mutex);

	printf("%#lx:\n我购买了一辆3.0T 510马力的L6双涡轮增压发动机的宝马 M4\n",pthread_self());

	//解锁
	pthread_mutex_unlock(&mutex);

	//退出线程
	pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
	//初始化条件变量
	//初始化互斥锁
	//创建两个线程,分别是生产者和消费者
	pthread_t tid1,tid2,tid3,tid4,tid5,tid6;
	if(pthread_create(&tid1,NULL,task1,NULL)!=0)
	{
		printf("tid1 create error\n");
		return 0;
	}

	if(pthread_create(&tid2,NULL,task2,NULL)!=0)
	{
		printf("tid2 create error\n");
		return 0;
	}

	if(pthread_create(&tid3,NULL,task2,NULL)!=0)
	{
		printf("tid2 create error\n");
		return 0;
	}

	if(pthread_create(&tid4,NULL,task2,NULL)!=0)
	{
		printf("tid2 create error\n");
		return 0;
	}
	
	if(pthread_create(&tid5,NULL,task2,NULL)!=0)
	{
		printf("tid2 create error\n");
		return 0;
	}

	if(pthread_create(&tid6,NULL,task2,NULL)!=0)
	{
		printf("tid2 create error\n");
		return 0;
	}


	printf("tid1=%#lx,tid2=%#lx,tid3=%#lx,tid4=%#lx,tid5=%#lx,tid6=%#lx\n",tid1,tid2,tid3,tid4,tid5,tid6);

	//回收线程资源
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	pthread_join(tid3,NULL);
	pthread_join(tid4,NULL);
	pthread_join(tid5,NULL);
	pthread_join(tid6,NULL);

	//销毁条件变量
	pthread_cond_destroy(&cond);

	//销毁互斥锁
	pthread_mutex_destroy(&mutex);

	return 0;
}

4> 将无名管道的代码实现重新敲一遍

#include<myhead.h>
int main(int argc, const char *argv[])
{
	//创造管道文件
	int pipefd[2] = {0};
	if(pipe(pipefd) ==-1)
	{
		perror("pipe eooro\n");
		return -1;
	}
	printf("pipefd[0]=%d,pipefd[1]=%d\n",pipefd[0],pipefd[1]);

	//创建一个子进程
	pid_t pid=fork();
	if(pid>0)
	{
		//父进程
		//关闭管道文件
		close(pipefd[0]);

		char wbuf[128]="";

		while(1)
		{
			bzero(wbuf,sizeof(wbuf));

			fgets(wbuf,sizeof(wbuf),stdin);
			wbuf[strlen(wbuf)-1] =0;

			//将数据写入管道文件中
			write(pipefd[1],wbuf,strlen(wbuf));

			//对写入的数据进行判断
			if(strcmp(wbuf ,"quit")==0)
			{
				break;
			}

		}

		//关闭写端
		close(pipefd[1]);

		wait(NULL); 	//阻塞回收进程资源
	}

	else if(pid==0)
	{
		//子进程
		//关闭写端
		close(pipefd[1]);

		char rbuf[128]="";

		while(1)
		{
			//清空rbuf
			bzero(rbuf,sizeof(rbuf));

			//从管道文件中读取数据
			read(pipefd[0],rbuf,sizeof(rbuf));

			//输出rbuf的数据
			printf("父进程传来的数据为: %s\n",rbuf);

			//对读取数据进行判断
			if(strcmp(rbuf ,"quit")==0)
			{
				break;
			}

		}

		//关闭读端
		close(pipefd[0]);

		//退出进程
		exit(EXIT_SUCCESS);
		
	}
	else
	{
		perror("fork error");
		return -1;
	}
	return 0;
}

5> 将有名管道的代码实现重新敲一遍

//create.c

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //创建一个管道文件
    if(mkfifo("./myfifo", 0664) == -1)
    {
        perror("mkfifo error");
        return -1;
    }

    getchar();       //阻塞

    system("rm myfifo");

    return 0;
}

//send.c

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //打开管道文件
    int wfd = -1;
    //以只写的形式打开文件
    if((wfd = open("./myfifo", O_WRONLY)) == -1)
    {
        perror("open error");
        return -1;
    }

    //定义容器
    char wbuf[128] = "";
    while(1)
    {
        printf("请输入>>>");
        fgets(wbuf, sizeof(wbuf), stdin);
        wbuf[strlen(wbuf)-1] = 0;

        //将数据写入管道
        write(wfd, wbuf, strlen(wbuf));

        //判断结果
        if(strcmp(wbuf,"quit") == 0)
        {
            break;
        }
    }



    //关闭文件
    close(wfd);


    return 0;
}

//receive.c

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //打开管道文件
    int rfd = -1;
    //以只写读的形式打开文件
    if((rfd = open("./myfifo", O_RDONLY)) == -1)
    {
        perror("open error");
        return -1;
    }

    //定义容器
    char rbuf[128] = "";
    while(1)
    {
        //清空数组
        bzero(rbuf, sizeof(rbuf));
        
        //读取管道中的数据
        read(rfd, rbuf, sizeof(rbuf));

        //输出结果
        printf("收到的数据为:%s\n", rbuf);

        //判断结果
        if(strcmp(rbuf,"quit") == 0)
        {
            break;
        }
    }



    //关闭文件
    close(rfd);


    return 0;
}

6> 使用有名管道完成两个进程的相互通信(提示:可以使用多进程或多线程完成)

//create.c

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //创建两个管道文件
	//A向B发送信息的通道
    if(mkfifo("./AtoB", 0664) == -1)
    {
        perror("AtoB error");
        return -1;
    }
	//B向A发送信息的通道
    if(mkfifo("./BtoA", 0664) == -1)
    {
        perror("BtoA error");
        return -1;
    }

	//阻塞
    getchar();     
	//清楚文件
    system("rm AtoB");
    system("rm BtoA");

    return 0;
}

AtoB

#include<myhead.h>

int main(int argc, const char *argv[])
{
	//创建进程
	pid_t pid=fork();
	if(pid>0)
	{
		//打开管道文件
    	int wfd = -1;
    	//以只写的形式打开文件
		if((wfd = open("./AtoB", O_WRONLY)) == -1)
   		 {
       		 perror("open error");
			 return -1;
		 }
		//定义容器	
    	char wbuf[128] = "";
    	while(1)
		{
			sleep(1);
			printf("请输入>>>");
			fgets(wbuf, sizeof(wbuf), stdin);
			//将\n变\0
        	wbuf[strlen(wbuf)-1] = 0;
	
    	    //将数据写入管道
        	write(wfd, wbuf, strlen(wbuf));
	
    	    //判断结果
			if(strcmp(wbuf,"quit") == 0)
			{
				//关闭文件
				close(wfd);

				break;
			}
		}
	}

	else if(pid==0)
	{
		//打开管道文件
		 int rfd = -1;
		 //以只读的形式打开文件
   		 if((rfd = open("./BtoA", O_RDONLY)) == -1)
   		 {
       		 perror("open error");
       		 return -1;
  		  }

  		  //定义容器
   		 char rbuf[128] = "";
		 while(1)
   		 {
			 
			sleep(1);
       		 //清空rbuf
			 bzero(rbuf,sizeof(rbuf));
			 //读取管道文件的数据
			 read(rfd,rbuf,sizeof(rbuf));
			 //输出结果
			 printf("收到的数据为: %s\n",rbuf);

			 //判断结果
			 if(strcmp(rbuf,"quit") == 0)
			 {
				 //关闭文件
				 close(rfd);

				 break;
			 }
		 }
	}
	else 
	{
		perror("fork error");
		return -1;
	}

    return 0;
}

BtoA

#include<myhead.h>

int main(int argc, const char *argv[])
{
	//创建进程
	pid_t pid=fork();

	 if(pid>0)
	{
		//打开管道文件
		int rfd = -1;
		 //以只读的形式打开文件
   		 if((rfd = open("./AtoB", O_RDONLY)) == -1)
   		 {
       		 perror("open error");
       		 return -1;
  		  }

  		  //定义容器
   		 char rbuf[128] = "";
		 while(1)
   		 {
			sleep(1);
       		 //清空rbuf
			 bzero(rbuf,sizeof(rbuf));
			 //读取管道文件的数据
			 read(rfd,rbuf,sizeof(rbuf));
			 //输出结果
			 printf("收到的数据为: %s\n",rbuf);

			 //判断结果
			 if(strcmp(rbuf,"quit") == 0)
			 {	
				 //关闭文件
				 close(rfd);

				 break;
			 }
		 }
	}
	else if(pid==0)
	{
		//打开管道文件
    	int wfd = -1;
    	//以只写的形式打开文件
		if((wfd = open("./BtoA", O_WRONLY)) == -1)
   		 {
       		 perror("open error");
			 return -1;
		 }
		//定义容器
		char wbuf[128] = "";
		while(1)
		{
			sleep(1);
			printf("请输入>>>");
			fgets(wbuf, sizeof(wbuf), stdin);
			//将\n变\0
			wbuf[strlen(wbuf)-1] = 0;

			//将数据写入管道
			write(wfd, wbuf, strlen(wbuf));

			//判断结果
			if(strcmp(wbuf,"quit") == 0)
			{
				//关闭文件
				close(wfd);
				break;
			}
		}
	}
	else 
	{
		perror("fork error");
		return -1;
	}

    return 0;
}

思维导图

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值