4月3日作业

这篇文章展示了如何使用C语言进行多线程编程,通过互斥锁、条件变量以及信号量来实现文件内容的并发读取与打印,以及控制线程的执行顺序。示例代码中包含了线程同步的典型应用,如文件读写、线程间通信和顺序打印任务。
摘要由CSDN通过智能技术生成

1、将一个文件中的数据打印到终端,类似cat一个文件,要求如下

        a.一个线程读取文件中的数据
        b.另外一个线程打印文件中的数据

程序代码

  1 #include<stdio.h>
  2 #include<pthread.h>
  3 #include<string.h>
  4 
  5 //互斥所
  6 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  7 
  8 //条件变量
  9 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
 10 
 11 
 12 struct cat_dir
 13 {
 14     int flag;
 15     FILE* fd;
 16     pthread_t tid_read;
 17     pthread_t tid_write;
 18     char buf;
 19 };
 20 
 21 void *callBack_read(void *arv)
 22 {
 23     while(1)
 24     {
 25         pthread_mutex_lock(&mutex);//上锁
 26 
 27         if(0 == (((struct cat_dir *)arv)->flag))
 28         {
 29             //实现读取任务
 30             if(0==fread(&(((struct cat_dir*)arv)->buf),1,1,((struct cat_dir*)arv)->fd))
 31             {
 32                 pthread_cond_wait(&cond,&mutex);
 33                 ((struct cat_dir*)arv)->flag=2;
 34                 break;
 35 
 36             }
 37 
 38             pthread_cond_wait(&cond,&mutex);
 39         }
 40 
 41 
 42         (((struct cat_dir *)arv)->flag) = 1;
 43 
 44         pthread_cond_signal(&cond);
 45 
 46         pthread_mutex_unlock(&mutex);
 47     }
 48     pthread_exit(NULL);
 49 }
 50 
 51 void *callBack_write(void *arv)
 52 {
 53     while(1)
 54     {
 55         if(((struct cat_dir*)arv)->flag == 2)
 56             break;
 57         pthread_mutex_lock(&mutex);//上锁
 58         if(1 == (((struct cat_dir *)arv)->flag))
 59         {
 60             //实现读取任务
 61             fwrite(&(((struct cat_dir*)arv)->buf),1,1,stdout);
 62             fflush(stdout);
 63             pthread_cond_wait(&cond,&mutex);
 64         }
 65 
 66         (((struct cat_dir *)arv)->flag) = 0;
 67         pthread_cond_signal(&cond);
 68         pthread_mutex_unlock(&mutex);
 69 
 70     }
 71     pthread_exit(NULL);
 72 }
 73 
 74 
 75 int main(int argc, const char *argv[])
 76 {
 77     struct cat_dir cat_dir1;
 78     cat_dir1.flag = 0;
 79     cat_dir1.fd=fopen("./daoxv.c","r");
 80 
 81     pthread_create(&cat_dir1.tid_read,NULL,callBack_read,&cat_dir1);
 82     pthread_create(&cat_dir1.tid_write,NULL,callBack_write,&cat_dir1);
 83 
 84     pthread_join(cat_dir1.tid_read,NULL);
 85     pthread_join(cat_dir1.tid_write,NULL);
 86 
 87     pthread_mutex_destroy(&mutex);
 88     pthread_cond_destroy(&cond);
 89 
 90                                                                                                                                                                                                                                                                                                                                                                                                
 91     return 0;
 92 }

运行结果:

ubuntu@ubuntu:练习$ gcc cat.c -pthread
ubuntu@ubuntu:练习$ ./a.out 
#include <stdio.h>
#include<pthread.h>
#include<unistd.h>

int flag=0;
//临界资源
char buf[]={"1234567"};
//互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *callBack(void *arg)
{
	while(1)
	{
		/********临界区********/
		pthread_mutex_lock(&mutex);
		
		//当不是当前线程要访问的时机,则让当前线程休眠
		if(1 == flag)
		{
			fprintf(stdout,"%s\n",buf);
			//设置条件变量(唤醒条件),同时解开互斥锁
			//休眠,等待被唤醒
			pthread_cond_wait(&cond,&mutex);
			//被节开始,会尝试上锁,如果上锁成功,则唤醒成功
			//当成功被唤醒后,会从当前位置继续向后执行
			//如果上锁失败,则重新回到cond上继续休眠
		}


		flag = 0;

		pthread_cond_signal(&cond);

		pthread_mutex_unlock(&mutex);
		/************临界区************/
	}
	pthread_exit(NULL);
}

void main()
{
	pthread_t pid;
	int *b=NULL;
	if(pthread_create(&pid,NULL,callBack,&b)!=0)
	{
		printf("create failed\n");
		return ;
	}

	char i,j;
	while(1)
	{
		/**********临界区************/
		pthread_mutex_lock(&mutex);

		if(0 == flag)
		{
			for(i=0,j=6;i<j;i++,j--)
			{
				buf[i]=buf[i]+buf[j];
				buf[j]=buf[i]-buf[j];
				buf[i]=buf[i]-buf[j];
			}
			//设置条件变量(唤醒条件),同时解开互斥锁
			//休眠,等待被唤醒
			pthread_cond_wait(&cond,&mutex);	
			//当被尝试唤醒时,会先尝上锁,如水果上锁成功,则唤醒成功
			//当成功被唤醒后,会从当前位置继续往后执行
			//如果上锁失败,则重新回到cond上继续休眠
		}

		flag = 1;

		//通过指定条件变量唤醒指定线程
		pthread_cond_signal(&cond);

		
		pthread_mutex_unlock(&mutex); //解锁
		/**********临界区************/
	}
}
ubuntu@ubuntu:练习$ 

小结一下:fread这个函数真的难用,里面size填大了容易出问题,填小了运行起来慢!

2、用信号量的方式实现倒置线程,打印线程的顺序执行

程序代码

  1 #include <stdio.h>
  2 #include<pthread.h>
  3 #include<unistd.h>
  4 #include<semaphore.h>
  5 char buf[]={"1234567"};
  6 sem_t sem1,sem2;
  7 void *callBack(void *arg)
  8 {
  9     while(1)
 10     /**********临界区*********/
 11     {
 12 
 13     sem_post(&sem2); //P操作
 14     //  if(1 == flag)
 15     //  {
 16             fprintf(stdout,"%s\n",buf);
 17     //  }   
 18     //  flag = 0;
 19     sem_wait(&sem1);//p操作
 20     sem_wait(&sem1); //P操作
 21     sem_post(&sem1);//V操作
 22     }
 23     /*********临界区*********/
 24 }
 25 
 26 void main()
 27 {
 28     pthread_t pid;
 29     sem_init(&sem1,0,1);
 30     sem_init(&sem2,0,1);
 31     int *b=NULL;
 32     if(pthread_create(&pid,NULL,callBack,&b)!=0)
 33     {
 34         printf("create failed\n");
 35         return ;
 36     }
 37 
 38     char i,j;
 39     while(1)
 40     {
 41     sem_post(&sem1);
 42     //  if(0 == flag)
 43     //  {
 44             for(i=0,j=6;i<j;i++,j--)
 45             {
 46                 buf[i]=buf[i]+buf[j];
 47                 buf[j]=buf[i]-buf[j];
 48                 buf[i]=buf[i]-buf[j];
 49             }
 50     //      flag = 1;                                                                                                                                                                        
 51     //  }
 52     sem_wait(&sem2);
 53     sem_wait(&sem2);
 54     sem_post(&sem2);
 55     }
 56     sem_destroy(&sem1);
 57 }

运行结果

7654321
1234567
7654321
1234567
7654321^C
ubuntu@ubuntu:作业$ 

3、现有ID号为a,b,c的三个线程,每个线程的任务都是循环打印自己的id号,要求打印的顺序为a,b,c

程序代码

  1 #include<stdio.h>
  2 #include<pthread.h>
  3 
  4 //定义一个全局变量flag,用于实现顺序打印
  5 int flag=1;
  6 int count = 0;
  7 //创建并申请一把互斥锁
  8 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  9 
 10 //创建并申请三个条件变量
 11 pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
 12 pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
 13 pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;
 14 
 15 
 16 void *callBack1(void *arv)
 17 {
 18     while(1)
 19     {
 20         /**********临界区*********/
 21         //进入临界区,上锁
 22         pthread_mutex_lock(&mutex);
 23 
 24         if(flag != 1)
 25             pthread_cond_wait(&cond1,&mutex);
 26 
 27         if(1 ==flag)
 28         {
 29             flag = 2;
 30             printf("pid2=%ld\n",*(pthread_t*)arv);
 31 
 32             count++;
 33             //该线程完成任务,进入休眠
 34         }
 35 
 36         //唤醒谁在条件变量上的线程
 37         pthread_cond_signal(&cond2);
 38         pthread_cond_signal(&cond3);
 39 
 40 
 41         //解锁
 42         pthread_mutex_unlock(&mutex);
 43         if(count>10)
 44             break;
 45         /**********临界区*********/
 46     }
 47     pthread_exit(NULL);
 48 }
 49 
 50 
 51 void *callBack2(void *arv)
 52 {
 53 
 54     while(1)
 55     {
 56         /**********临界区*********/
 57         pthread_mutex_lock(&mutex);
 58 
 59         if(flag != 2)
 60             pthread_cond_wait(&cond2,&mutex);
 61 
 62         if(2 == flag)
 63         {
 64 
 65             flag = 3;
 66             printf("pid2=%ld\n",*(pthread_t*)arv);
 67             count++;
 68 
 69         }
 70         /**********临界区*********/
 71         pthread_cond_signal(&cond1);
 72 
 73         pthread_cond_signal(&cond3);
 74 
 75         pthread_mutex_unlock(&mutex);
 76         if(count>10)
 77             break;
 78     }
 79 
 80     pthread_exit(NULL);
 81 }
 82 
 83 
 84 void *callBack3(void *arv)
 85 {
 86     while(1)
 87     {
 88         /**********临界区*********/
 89         pthread_mutex_lock(&mutex);
 90 
 91         if(flag != 3)
 92             pthread_cond_wait(&cond3,&mutex);
 93 
 94         if(3 == flag)
 95         {
 96             flag = 1;
 97             printf("pid3=%ld\n",*(pthread_t*)arv);
 98             count++;
 99         }
100 
101         /**********临界区*********/
102         pthread_cond_signal(&cond1);
103 
104         pthread_cond_signal(&cond2);
105 
106 
107         pthread_mutex_unlock(&mutex);
108         if(count>10)
109             break;
110     }
111 
112     pthread_exit(NULL);
113                                                                                                                                                                                                                                                                                                               
114 }
115 
116 
117 int main(int argc, const char *argv[])
118 {
119     //创建三个线程
120     pthread_t pid1,pid2,pid3;
121     pthread_create(&pid1,NULL,callBack1,&pid1);
122     pthread_create(&pid2,NULL,callBack2,&pid2);
123     pthread_create(&pid3,NULL,callBack3,&pid3);
124 
125 
126     //阻塞接受三个子线程的返回值
127     pthread_join(pid1,NULL);
128     pthread_join(pid2,NULL);
129     pthread_join(pid3,NULL);
130 
131     //关闭互斥锁
132     pthread_mutex_destroy(&mutex);
133 
134     //关闭条件变量
135     pthread_cond_destroy(&cond1);
136     pthread_cond_destroy(&cond2);
137     pthread_cond_destroy(&cond3);
138     return 0;
139 }
~                                        

运行结果

ubuntu@ubuntu:作业$ gcc printf_abc.c -pthread
ubuntu@ubuntu:作业$ ./a.out 
pid2=140209787340544
pid2=140209778947840
pid3=140209770555136
pid2=140209787340544
pid2=140209778947840
pid3=140209770555136
pid2=140209787340544
pid2=140209778947840
pid3=140209770555136
pid2=140209787340544
pid2=140209778947840
pid3=140209770555136
pid2=140209787340544
ubuntu@ubuntu:作业$ 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

malingshu404

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值