Linux练习_线程练习

Posted Leslie X徐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux练习_线程练习相关的知识,希望对你有一定的参考价值。

线程练习

题1

要求:

  • 创建3个子线程a,b,c,再创建一个线程回收线程z
  • 在z线程内循环调用join来回收a,b,c线程
  • 并且将abc线程返回值打包成数组在main主函数中输出
  • 使用分离式的专用线程来回收线程
/*
 * 线程资源回收线程.c
 * 创建3个子线程a,b,c,再创建一个线程回收线程z
 * 在z线程内循环调用join来回收a,b,c线程
 * 并且将abc线程返回值打包成数组在main主函数中输出
 */


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

int i,result[3];
pthread_t a,b,c,z;

void* th_fn(void* arg)
{
	printf("pthread start!\\n");
	pthread_exit((void*)i++);
}

void* clean(void* arg)
{
	printf("clean start!\\n");
	pthread_join(a,(void*)&result[2]);
	pthread_join(b,(void*)&result[1]);
	pthread_join(c,(void*)&result[0]);
	return NULL;
}

int main(int argc, char **argv)
{
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
	
	pthread_create(&a,NULL,th_fn,NULL);
	pthread_create(&b,NULL,th_fn,NULL);
	pthread_create(&c,NULL,th_fn,NULL);
	pthread_create(&z,&attr,clean,NULL);
	
	sleep(1); //主线程需要休眠1s来让线程执行完毕
	
	pthread_attr_destroy(&attr);
	
	int j=3;
	while(j--)printf("%d\\n",result[j]);
	
	return 0;
}

输出:

pthread start!
pthread start!
clean start!
pthread start!
0
1
2

  • 使用清理函数编写(cleanup_pop&push)
/*
 * 线程资源回收线程.c
 * 创建3个子线程a,b,c,再创建一个线程清理函数
 */


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

int i,result[3];
pthread_t a,b,c;

void* th_fn(void* arg)
{
	printf("pthread start!\\n");
	return (void*)i++;
}

void clean(void* arg)
{
	printf("clean start!\\n");
	pthread_join(a,(void*)&result[2]);
	pthread_join(b,(void*)&result[1]);
	pthread_join(c,(void*)&result[0]);
	
	return;
}

int main(int argc, char **argv)
{	
	//添加清理函数
	pthread_cleanup_push(clean,0);
	
	pthread_create(&a,0,th_fn,0);
	pthread_create(&b,0,th_fn,0);
	pthread_create(&c,0,th_fn,0);
	
	//清理函数使用
	pthread_cleanup_pop(1);
	
	int j=3;
	while(j--)printf("%d\\n",result[j]);
	
	return 0;
}


  • 使用cancel:cancel无法获取返回值,也无法清理资源
/*
 * 线程资源回收线程.c
 * 创建3个子线程a,b,c,再创建一个线程回收函数
 使用pthread_cancel回收线程
 */


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

int i,result[3];
pthread_t a,b,c;

void* th_fn(void* arg)
{
	printf("pthread start!\\n");
	result[i]=i;
	++i;
	pthread_exit(NULL);
}

void clean(void* arg)
{
	printf("clean start!\\n");
	pthread_cancel(a);
	pthread_cancel(b);
	pthread_cancel(c);
	
	return;
}

int main(int argc, char **argv)
{	
	//添加清理函数
	pthread_cleanup_push(clean,0);
	
	pthread_create(&a,0,th_fn,0);
	pthread_create(&b,0,th_fn,0);
	pthread_create(&c,0,th_fn,0);
	//注意需要将线程设置为分离式
	pthread_detach(a);
	pthread_detach(b);
	pthread_detach(c);
	
	//清理函数使用
	pthread_cleanup_pop(1);
	
	int j=3;
	while(j--)printf("%d\\n",result[j]);
	
	return 0;
}

输出:

pthread start!
pthread start!
clean start!
pthread start!
2
1
0

题2

cancel的使用:

/*
 * pthread_cancel的使用.c
 * 
 */

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

void* th_fn(void* arg)
{
	//pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,0);
	//pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,0);
	printf("1\\n");
	printf("2\\n");
	pthread_cancel(pthread_self());
	printf("3\\n");
	pthread_testcancel();
	printf("4\\n");
	return (void*)0;
}

int main(int argc, char **argv)
{
	while(1){
		pthread_t thread;
		pthread_create(&thread, 0,th_fn,0);
		pthread_detach(thread);
	}
	return 0;
}


题3

自己写同步逻辑,缺点是:它不是原子操作,会受到时间片的影响导致逻辑错误。
原子操作:在一个原子操作中,无论时间片是否使用完毕,原子操作总是在完整执行后才会释放时间片。

题4

轮流打印AB

  • 使用互斥锁,实现两个线程轮流打印A-B-A-B
  • 其中 ‘-’ 代表睡眠1秒,1s输出一个字符
    代码:
/*
 * 轮流打印AB.c
 * 使用互斥锁,实现两个线程轮流打印A-B-A-B
 * 其中 '-' 代表睡眠1秒,1s输出一个字符
 */


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

typedef struct data{
	char ch;
	pthread_mutex_t mutex;
	}xdata;
xdata dataX;

pthread_t tha,thb;

void* tha_fn(void* arg)
{
	while(1){
		pthread_mutex_lock(&dataX.mutex);
		dataX.ch='A';
		
		printf("%c\\n",dataX.ch);
		sleep(1); //等待1s
		pthread_mutex_unlock(&dataX.mutex);
		sleep(1); //让B线程获取资源
	}
		
}

void* thb_fn(void* arg)
{
	while(1){
		pthread_mutex_lock(&dataX.mutex);
		dataX.ch='B';
		
		printf("%c\\n",dataX.ch);
		sleep(1); //等待1s
		pthread_mutex_unlock(&dataX.mutex);
		sleep(1); //让A线程获取资源
	}
		
}

void sig_handler(int signum)
{
	if(signum==SIGINT){
		pthread_mutex_unlock(&dataX.mutex);
		pthread_mutex_destroy(&dataX.mutex);
		pthread_cancel(tha);
		pthread_cancel(thb);
		printf("\\npthread end!\\n");
		exit(0);
	}
}

int main(int argc, char **argv)
{
	
	pthread_mutex_init(&dataX.mutex,0);
	
	pthread_create(&tha,0,tha_fn,0);
	pthread_create(&thb,0,thb_fn,0);
	pthread_detach(tha);
	pthread_detach(thb);
	
	signal(SIGINT,sig_handler);
	while(1);
	return 0;
}


题5

使用互斥锁实现主线程从键盘录入字符串,子线程统计字符串中字符的个数

/*
 * 3_str.c
*使用互斥锁实现主线程从键盘录入字符串,子线程统计字符串中字符的个数
 */


#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

struct data{
	char str[1024];
	pthread_mutex_t mutex;
}xdata;

void sig_handler(int signum)
{
	if(signum==SIGINT){
		pthread_mutex_destroy(&xdata.mutex);
		printf("\\nthread end\\n");
		sleep(1);
		exit(0);
	}
}
	
void* th_fn1(void* arg)
{
	while(1){
		pthread_mutex_lock(&xdata.mutex);
		printf("strlen : %d\\n",strlen(xdata.str));
		pthread_mutex_unlock(&xdata.mutex);
		usleep(100);
	}
}


int main(int argc, char **argv)
{	
	pthread_t th1;
	pthread_create(&th1,0,th_fn1,0);
	pthread_mutex_init(&xdata.mutex,0);
	while(1){
		pthread_mutex_lock(&xdata.mutex);
		printf("请输入字符串:");
		scanf("%s",xdata.str);
		pthread_mutex_unlock(&xdata.mutex);
		usleep(100);
		signal(SIGINT,sig_handler);
	}
	return 0;
}


题6:模拟服务器和客户端

要求:

  • 编写3个.c文件1,2,3
  • 其中 文件1模拟成服务器,文件2和3模拟成客户端
  • 文件1要求有3个线程:主线程、处理文件2事物的线程、处理文件3线程
  • 文件2发送一个信号给文件1,文件3发送另一个信号给文件1
  • 1在接受信号后,分别打开文件io写入不同的数据
  • 注意文件1 过程当中的同步问题

1号文件:

/*
 * 1.c
 * 编写3个.c文件1,2,3
 * 其中 文件1模拟成服务器,文件2和3模拟成客户端
 * 文件1要求有3个线程:主线程、处理文件2事物的线程、处理文件3线程
 * 文件2发送一个信号给文件1,文件3发送另一个信号给文件1
 * 1在接受信号后,分别打开文件io写入不同的数据
 * 注意文件1 过程当中的同步问题
 * 
 */

#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

pthread_t th2,th3;
char *fifo2="my_fifo2", *fifo3="my_fifo3";

void sig_handler(int signum){
	if(signum==SIGUSR1){
		printf("2号发送消息\\n");
	}
	if(signum==SIGUSR2){
		printf("3号发送消息\\n");
	}
	if(signum==SIGINT){
		remove(fifo2);
		remove(fifo3);
		printf("\\n程序结束\\n");
		exit(0);
	}
}

void* th2_fn(void* arg){
	signal(SIGUSR1,sig_handler);
	return NULL;
}

void* th3_fn(void* arg){
	signal(SIGUSR2,sig_handler);
	return NULL;
}

int main(int argc, char **argv)
{
	int pid = getpid();
	int fifofd2,fifofd3;
	mkfifo(fifo2,0666);
	fifofd2 = open(fifo2,O_WRONLY);
	write(fifofd2,&pid,sizeof(int));
	close(fifofd2);
	
	mkfifo(fifo3,0666);
	fifofd3 = open(fifo3,O_WRONLY);
	write(fifofd3,&pid,sizeof(int));
	close(fifofd3);
	
	pthread_create(&th2,0,th2_fn,0);
	pthread_create(&th3,0,th3_fn,0);
	pthread_detach(th2);
	pthread_detach(th3);
	signal(SIGINT,sig_handler);
	while(1);
	return 0;
}


2号文件:

/*
 * 2.c
 */

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>

int main_pid;

void sig_handler(int signum){
	if(signum==SIGINT){
		kill(main_pid,SIGUSR1);
	}
}

int main(int argc, char **argv)
{
	printf("按ctl+C向1发送信号\\n按ctrl+\\\\结束\\n");
	int fifofd2;
	mkfifo("my_fifo2",0666);
	fifofd2 = open("my_fifo2",O_RDONLY);
	read(fifofd2,&main_pid,sizeof(int));
	close(fifofd2);
	
	signal(SIGINT,sig_handler);
	while(1);
	return 0;
}


3号文件:

/*
 * 3.c
 * 
 * 
 */

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>

int main_pid;

void sig_handler(int signum){
	if(signum==SIGINT){
		kill(main_pid,SIGUSR2);
	}
}

int main(int argc, char **argv)
{
	printf("按ctl+C向1发送信号\\n按ctrl+\\\\结束\\n");
	int fifofd3;
	mkfifo("my_fifo3",0666);
	fifofd3 = open("my_fifo3",O_RDONLY);
	read(fifofd3,以上是关于Linux练习_线程练习的主要内容,如果未能解决你的问题,请参考以下文章

linux套接字编程之多进程多线程练习

02027_线程池练习:返回两个数相加的结果

Python练习册 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-),(http://tieba.baidu.com/p/2166231880)(代码片段

多线程并发练习(Day35)

Linux练习_进程间信号练习

Linux下基于TCP协议的群聊系统设计(多线程+select)