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:作业$