线程

一、线程

1、什么是线程

1、线程:是CPU调度的基本单元
进程:是可独立的运行模块
线程依赖于进程,不能独立存在
线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属于一个进程的其他的线程共享进程拥有的全部资源。
2、刚启动运行的线程称为主线程,其他创建的线程乘为其他线程
对于线程而言,多个线程没有地址空间,共享进程地址空间
在这里插入图片描述

2、线程与进程的区别

1、和进程相比,它是一种非常"节俭"的多任务操作方式。在linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。

2、运行于一个进程中的多个线程,它们之间使用相同的地址空间,而且线程间彼此切换所需时间也远远小于进程间切换所需要的时间。据统计,一个进程的开销大约是一个线程开销的30倍左右。

3、线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过进程间通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进城下的线程之间贡献数据空间,所以一个线程的数据可以直接为其他线程所用,这不仅快捷,而且方便。

4、多线程程序作为一种多任务、并发的工作方式,还有如下优点:
(1)使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
(2)改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序才会利于理解和修改。

三、线程的创建

1、线程的创建用int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
第一个参数:指向pthread_t类型的指针,用于引用新创建的线程。
第二个参数:用于设置线程的属性,一般不需要特殊的属性,所以可以简单地设置为NULL。
第三个参数:传递新线程所要执行的函数地址。
第四个参数:新线程所要执行的函数的参数。

//pthread_creat
//线程创建
#include <stdio.h>
#include <pthread.h>

void *work(void *i)
{
	long num = (long)i;
	while(1)
	{
		printf("num = %ld\n",num);
		sleep(1);
	}
}

int main()
{
	//1、线程的id,外调参数,需要传指针过去
	//2、设置线程大小,一般写NULL
	//3、工作函数
	//4、工作函数的参数
	//返回值0为成功
	pthread_t thread;
	int pd = pthread_create(&thread,NULL,work,(void *)20);
	if(pd != 0)
	{
		printf("创建线程失败\n");
		return -1;
	}
	while(1)
	{
		printf("s = %d\n",10);
		sleep(1);
	}
	
	return 0;
}

四、线程的回收

线程的回收可以使用2种 方式
1、线程等待
int pthread_join(pthread_t th, void **thread_return);
第一个参数:将要等待的线程,线程通过pthread_create返回的标识符来指定。
第二个参数:一个指针,指向另一个指针,而后者指向线程的返回值。不需要返回值则为NULL。
注意:pthread_join是一个阻塞型的函数,只能回收单个线程

//pthread_create,pthread_self,pthread_exit,pthread_join
//创建,查看线程id,线程退出,类似于return,线程回收(阻塞型的)
#include <stdio.h>
#include <pthread.h>

void *work()
{
	printf("线程id = %ld\n",pthread_self());
	sleep(2);
	
	//return "hello";
	pthread_exit("hello");
}

int main()
{
	//1、线程的id,外调参数,需要传指针过去
	//2、设置线程大小,一般写NULL
	//3、工作函数
	//4、工作函数的参数
	//返回值0为成功
	pthread_t thread;
	pthread_create(&thread,NULL,work,NULL);
	
	char *a;
	//进程回收(1)阻塞型的
	//1、回收线程的id
	//2、线程函数的返回值
	//pthread_join()操作可以由任何一个同组的线程发起,不必是主线程
	pthread_join(thread,(void **)&a);
	
	printf("主线程id = %ld,%s\n",pthread_self(),a);
	
	return 0;
}

2、线程分离
int pthread_detach(pthread_t thread);
参数:将要分离的线程
成功返回0。失败返回错误值
注意:pthread_detach是一个非阻塞型的函数,主线程退出后其他线程直接退出。
在主线程里面使用pthread_exit,其他线程会执行结束后在退出。

//pthread_create,pthread_detach,pthread_exit
//线程创建,线程分离(由系统处理,非阻塞型),线程退出(在主线程中使用,用于令其他线程函数执行完毕)
#include <stdio.h>
#include <pthread.h>

void *work()
{
	sleep(2);
	printf("线程id = %ld\n",pthread_self());
}

int main()
{
	//1、线程的id,外调参数,需要传指针过去
	//2、设置线程大小,一般写NULL
	//3、工作函数
	//4、工作函数的参数
	//返回值0为成功
	pthread_t thread;
	pthread_create(&thread,NULL,work,NULL);
	
	//进程回收(2)非阻塞型的
	//1、回收线程的id
	//由于主线程退出后进程退出了,其他线程依赖于进程,因此也退出了
	pthread_detach(thread);
	
	printf("主线程id = %ld\n",pthread_self());

	pthread_exit(NULL);				//使用函数pthread_exit来使主线程退出后,其他线程进行执行结束后在退出
		
	//程序在上面就退出了,不会往下执行。
	//printf("主线程id = %ld\n",pthread_self());	
	
	return 0;
}

五、 查看线程id号

1、在线程内部使用pthread_self()函数,可以查看自身的id号

六、线程终止

1、void pthread_exit(void *retval);
参数:返回指针,线程的工作函数传回来的值,不需要的时候填NULL
注意:在主线程里面使用pthread_exit,其他线程会执行结束后在退出。

七、线程的注意事项

1、除了局部变量以外,所有其他变量都将在一个进程中的所有线程之间共享。
2、线程没有像进程那样的父子关系,仅有属于同一个进程的“同组”关系(进程实际上代表的是一个线程组)。
3、在POSIX线程模型中,主线程可以创建一个新线程A,新线程A又可以创建另一个新线程B,线程A和B本身没有父子关系,只是同属于一个进程。
4、等待线程结束的pthread_join()操作可以由任何一个同组的线程发起,不必是主线程。另外,如果主线程退出,即进程退出,则所有的线程也会随之退出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值