线程控制
- 第一题
完成了如下功能:线程1把1,2,3,…,10打印在屏幕上(每隔4秒钟打印一个);另一个线程2把11,12,…,20打印在屏幕上(每隔2秒钟打印一个)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
void *thread1_proc(void *arg)
{
int i=0;
while(i<10)
{
printf("thread1:%-5d",i);
fflush(stdout);//printf是基于行缓冲的:只有在缓冲区满、刷新缓冲区或者遇到换行符的时候才把字符串显示在屏幕上,所以手动调用fflush刷新缓冲区
sleep(4);
i++;
}
printf("Thread1 finished!\n");
pthread_exit(NULL);
}
void *thread2_proc(void *arg)
{
int i=10;
while(i<20)
{
printf("thread2:%-5d",i);
fflush(stdout);
sleep(2);
i++;
}
printf("Thread2 finished!\n");
pthread_exit(NULL);
}
void *m_thread_proc(void *arg){
/**
* if flag==1
* output 1-10 at intervals of four seconds
* else output 11-20 at intervals of two seconds
*/
int flag=(int)arg;
for(int i=flag==1?1:10;i<=10*flag;i++){
printf("thread2:%-5d",i);
fflush(stdout);
sleep(2*flag);
}
}
void *mm_thread_proc(void *arg){
int *marg=(int*)arg;
for(int i=marg[1];i<=marg[2];i++){
printf("thread%d:%-5d",marg[0],i);
fflush(stdout);
sleep(marg[3]);
}
}
int main()
{
pthread_t thread1,thread2;
int flag_1=1,flag_2=2;
// thread name [0]
// output [1]--[12]
// delay [2] s
int thread_1_arg[]={1,1,10,4};
int thread_2_arg[]={2,11,20,2};
/*
if(pthread_create(&thread1,NULL,thread1_proc,NULL)!=0)
perror("Create thread1 failed");
if(pthread_create(&thread2,NULL,thread2_proc,NULL)!=0)
perror("Create thread2 failed");
*/
/* m_thread_proc
if(pthread_create(&thread1,NULL,m_thread_proc,flag_1)!=0)
perror("Create thread1 failed");
if(pthread_create(&thread2,NULL,m_thread_proc,flag_2)!=0)
perror("Create thread2 failed");
*/
if(pthread_create(&thread1,NULL,mm_thread_proc,thread_1_arg)!=0)
perror("Create thread1 failed");
if(pthread_create(&thread2,NULL,mm_thread_proc,thread_2_arg)!=0)
perror("Create thread2 failed");
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
}
- 如果把参考代码中的两个pthread_join注释掉后会正常工作吗?为什么?
不会,如果没有pthread_join来阻塞等待子线程的话,主线程就提前结束了,没办法正常工作。
- 如果把thread2_proc函数中的pthread_exit换成exit,程序运行结果又有什么不同?
线程二在输出10个数之后,程序就结束了,exit函数是用来结束整个程序的,而pthread_exit是用来结束当前线程,而pthread_cancel可以用来结束其他子线程。
- 如果要求线程1、线程2共用同一个线程入口函数该如何修改代码?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W97d62L5-1616598008382)(https://i.loli.net/2021/03/24/FsHPtSCbDRq6JX9.jpg)]
- 第二题
(反复的过程,不能只做一次)主线程负责从键盘获取(1)两个整数,子线程负责对这两个整数完成求和(2)运算并把结果打印出来,请编程实现该功能,并尝试是否可以要利用全局变量完成两个线程的同步。
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
sem_t can_add;//能够进行加法计算的信号量
sem_t can_scanf;//能够从键盘输入的信号量
int x,y;
void *thread_add(void *arg)//加法线程入口函数
{
while(1)
{
sem_wait(&can_add);//申请信号量
printf("x+y=%d\n",x+y);
sem_post(&can_scanf);//释放信号量
}
}
int main()
{
pthread_t tid;
sem_init(&can_add,0,0);//初始化can_add信号量
sem_init(&can_scanf,0,1); //初始化can_scanf信号量
if(pthread_create(&tid,NULL,thread_add,NULL)<0)
{
printf("Create thread_add failed!\n");
exit(0);
}
while(1)
{
sem_wait(&can_scanf);//申请信号量
printf("Please input two integers:");
scanf("%d%d",&x,&y);
sem_post(&can_add);///释放信号量
}
}
- 使用全局变量来进行锁
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int x,y;
int can_add,can_scanf;
void *thread_add(void *arg)//加法线程入口函数
{
while(1)
{
if(can_add==1){
can_add=0;
printf("x+y=%d\n",x+y);
can_scanf=1;
}
}
}
int main()
{
pthread_t tid;
can_add=0;
can_scanf=1;
if(pthread_create(&tid,NULL,thread_add,NULL)<0)
{
printf("Create thread_add failed!\n");
exit(0);
}
while(1)
{
if(can_scanf==1){
can_scanf=0;
printf("Please input two integers:");
scanf("%d%d",&x,&y);
can_add=1;
}
}
}
-
第三题
利用信号量实现:
主线程负责从键盘获取两个整数,子线程1负责对这两个整数完成求和运算并把结果打印出来,子线程2负责对这两个整数完成乘法运算并打印出来。三个线程要求遵循如下同步顺序:
(1) 主线程获取两个数;
(2) 子线程1计算;
(3) 子线程2计算;
(4) 转(1)
#include <stdio.h> #include <semaphore.h> #include <pthread.h> #include <stdlib.h> sem_t can_add,can_scanf,can_mul; int x,y; void *thread_add(void *arg)//加法线程入口函数 { while(1) { sem_wait(&can_add);//申请加法信号量 printf("x+y=%d\n",x+y); sem_post(&can_mul);//释放乘法信号量 } } void *thread_mul(void *arg)//乘法法线程入口函数 { while(1) { sem_wait(&can_mul);//申请信号量 printf("x*y=%d\n",x*y); sem_post(&can_scanf);//释放信号量 } } int main() { pthread_t tid[2]; sem_init(&can_add,0,0); //初始化can_add信号量 sem_init(&can_scanf,0,1); //初始化can_scanf信号量 sem_init(&can_mul,0,0); //初始化can_scanf信号量 if(pthread_create(&tid[0],NULL,thread_add,NULL)<0) { printf("Create thread_add failed!\n"); exit(0); } if(pthread_create(&tid[1],NULL,thread_mul,NULL)<0) { printf("Create thread_mul failed!\n"); exit(0); } while(1) { sem_wait(&can_scanf);//申请信号量 printf("Please input two integers:"); scanf("%d%d",&x,&y); sem_post(&can_add);///释放信号量 } }