線程控制
- 第一題
完成了如下功能:線程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);///釋放信号量 } }