Linux下pthread实现多线程程序(一个线程控制两个线程的暂停、恢复、终止)

  • Post author:
  • Post category:linux


一、功能要求

使用三个线程,线程1用来监听用户输入和作为其他两个线程的监听器,线程2的主要内容为每隔一段时间,输出“hello 2”字符串,线程3的主要内容为每隔一段时间,输出“hello 3”字符串。根据输入的数据来改变线程1和线程2的状态

实现对线程的创建、暂停、恢复、终止等操作,通过输入数字来进行控制,具体来说,创建后默认是暂停的,

  • 1恢复线程2,2暂停线程2,3终止线程2,
  • 5恢复线程3,6暂停线程3,7终止线程3。

其中,恢复与暂停可以反复交替进行。

二、主要函数



pthread_create







UNIX环境创建线程函数



pthread_join:


用来等待一个线程的结束。

前两个、后两个成对使用,根据场景需要可交叉使用



pthread_mutex_lock:


互斥锁加锁



pthread_mutex_unlock:


互斥锁解锁



pthread_cond_signal:


条件唤醒



pthread_cond_wait:


条件等待

三、运行截图

为什么不能立即暂停/挂起线程,输入2或者6的时候线程2、3都会有一个输出?

答: 在线程1中读取的输入,在线程2、3中执行的暂停/挂起操作,并不能立即做出反应

四、主要代码

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>

/*
1恢复线程2,2暂停线程2,3终止线程2,
5恢复线程3,6暂停线程3,7终止线程3。
*/
static int input=0;   //接收键盘输入
static pthread_t id1,id2,id3;//线程1、2、3
//条件变量与互斥锁初始化
pthread_cond_t c2  = PTHREAD_COND_INITIALIZER;
pthread_cond_t c3  = PTHREAD_COND_INITIALIZER;
pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t m3 = PTHREAD_MUTEX_INITIALIZER;

//线程1
void FunOne(void) {
	//首次启动堵塞线程2、3
	pthread_mutex_lock(&m2);
	pthread_mutex_lock(&m3);
	while(1) {
		scanf("%d", &input);
		switch(input) {
			case 1:
				//恢复线程2;
				printf("恢复线程2...\n");
				pthread_cond_signal(&c2);//发送信号唤醒阻塞等待的进程
				pthread_mutex_unlock(&m2);//在while循环内会被多次调用
				break;
			case 3:
				//终止线程2;
				pthread_cancel(id2);
				printf("终止线程2...\n");
				break;
			case 5:
				//恢复线程3;
				printf("恢复线程3...\n");
				pthread_cond_signal(&c3);
				pthread_mutex_unlock(&m3);
				break;
			case 7:
				//终止线程3;
				pthread_cancel(id3);
				printf("终止线程3...\n");
				break;
		}
	}
}
//线程2
void FunTwo(void) {
	pthread_mutex_lock(&m2);
	while(1) {
		if(input==2) {
			printf("挂起线程2...\n");
			pthread_cond_wait(&c2, &m2);//执行这个函数的线程将会被挂起
		} else {
			sleep(2);
			printf("hello 2! \n");
		}
	}
	pthread_mutex_unlock(&m2);
}
//线程3
void FunThree(void) {
	pthread_mutex_lock(&m3);
	while(1) {
		if(input==6) {
			printf("挂起线程3...\n");
			pthread_cond_wait(&c3, &m3);//执行这个函数的线程将会被挂起
		} else {
			sleep(2);
			printf("hello 3! \n");
		}
	}
	pthread_mutex_unlock(&m3);
}

int main(int argc,char* argv[]) {

	int res1 = pthread_create (&id1, NULL, (void *) FunOne, NULL);
	sleep(1);//先让线程1抢占cpu,通过互斥锁让线程2、3阻塞
	int res2 = pthread_create (&id2, NULL, (void *) FunTwo, NULL);
	int res3 = pthread_create (&id3, NULL, (void *) FunThree, NULL);
	if(res1!=0||res2!=0||res3!=0) {
		printf("create error!\n");
		return -1;
	}
	/**
	*将进程阻塞,来执行指定线程
	*/
	pthread_join(id1,NULL);
	pthread_join(id2,NULL);
	pthread_join(id3,NULL);

	pthread_mutex_destroy(&m2);//销毁互斥锁
	pthread_mutex_destroy(&m3);//销毁互斥锁

	return 0;
}

五、总结

线程2、3的第一次暂停是因为线程1先对互斥锁上锁了,而后面线程2、3的暂停是因为它们自己在等待条件信号

这里不能只用一个互斥锁和一个条件变量来实现,当其中一个线程互斥锁解锁或者发送一个条件信号的时候,会唤醒其他正在等待的线程,并不能控制确定的一个线程的执行。可以通过设置一些全局变量来尝试控制。

代码可能存在其他问题,仅供参考!



版权声明:本文为qq_41548460原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。