线程概念
线程是进程的一部分,描述指令流执行状态。它是进程中的指令执行流的最小单位,是CPU调度的基本单位。线程可以看成是轻量级进程,是操作系统进行调度的最小单位。一个线程是一个任务(一个程序段)的一次执行过程。线程不占有内存空间,它包括在进程的内存空间中。在同一个进程内,多个线程共享进程的资源。一个进程至少有一个线程。
线程状态
操作系统创建线程时,线程处于创建态,CPU调度线程时,线程处于运行态,此时其它已创建的或者时间片到的线程就处于就绪态,当然还有些线程在进行磁盘、网络等IO时就处于阻塞态,操作系统销毁线程时,线程就处于终止态。另外,线程还具有静止就绪态和静止阻塞态,处于这两种状态,说明这个线程被操作系统挂起了,操作系统挂起线程,是为了观察和分析线程状态。
线程特点
小开销:和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间。
通信方便:对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。
并发执行:在一个进程中的多个线程之间,可以并发执行,甚至允许在一个进程中所有线程都能并发执行;同样,不同进程中的线程也能并发执行,充分利用和发挥了处理机与外围设备并行工作的能力。
资源共享:在同一进程中的各个线程,都可以共享该进程所拥有的资源,这首先表现在:所有线程都具有相同的地址空间(进程的地址空间),这意味着,线程可以访问该地址空间的每一个虚地址;此外,还可以访问进程所拥有的已打开文件、定时器、信号量机构等。由于同一个进程内的线程共享内存和文件,所以线程之间互相通信不必调用内核。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。
pthread_create()线程创建函数
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
成功时返回零,错误时返回错误码
参数一:为指向线程标识符的指针
参数二:用来设置线程属性,通常为NULL
参数三:函执行函数指针,该函数运行结束,则线程结束
参数四:传入线程执行函数的参数
pthread_join()线程等待退出函数
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
成功时返回零,错误时返回错误码
参数一:thread线程标识符
参数二:存储线程结束状态
pthread_exit()线程退出函数
#include <pthread.h>
void pthread_exit(void *retval);
返回值: 调用现成的返回值,可用其它函数pthread_join 来获取
参数retval为无类型指针,内容传给pthread_join函数的第二个参数
其他api:
pthread_self():获取自身线程id
int pthread_detach(pthread_t thread):实现线程分离,不再受主线程管理,由系统接任。线程结束后,其退出状态不由其他线程获取,而直接自己自动释放
代码示例
#include <stdio.h>
#include <pthread.h>
void *func1(void *arg)
{
static char *p = "t1 is run out";//必须定义static
printf("t1 id:%ld\n",(unsigned long)pthread_self());//打印线程func1线程id
printf("t1:param is %d\n",*((int *)arg));//打印参数arg
pthread_exit((void *)p);//线程退出
}
int main()
{
int param = 100;
pthread_t t1;
char *pret = NULL;//储存进程结束状态
if( pthread_create(&t1, NULL, func1,(void *)¶m) == 0)
{
printf("main:创造t1成功\n");
}
printf("main id:%ld\n",(unsigned long)pthread_self());//打印main线程id
pthread_join(t1,(void **)&pret);//等待线程退出
printf("main: t1退出: %s\n",pret);//打印线程结束状态
return 0;
}
编译运行