您的位置:首页 > 运维架构 > Linux

线程初识

2017-06-03 23:08 330 查看

线程的概念

1、在进程中,进程承担资源分配,而线程是调度的基本单位,线程在进程内部运行,那么,什么是线程呢?简单来说一个线程是进程的一个顺序执行流。同类的多个线程共享一块内存空间和一组系统资源,线程本身有一个供程序执行时的堆栈。线程在切换时负荷小,因此,线程也被称为轻负荷进程。一个进程中可以包含多个线程。linux中线程又称为轻量级进程。

线程的特点:

我们已经知道进程主要是独占系统资源,独享系统地址空间;而线程相反,可以共享系统资源,尽管线程相对于进程可以共享系统资源,但是,它也有自己独有的,每个线程独有它的硬件上下文信息和私有栈(各种临时变量,不至于混乱);进程间通信需要借助系统中你的通信机制在:匿名管道(pipe)、命名管道(fifo)、消息队列、信号量和共享内存机制,这些通信机制将占用大量的系统资源,特别是在进行少量数据传递时显得过于庞大,而线程可以访问进程所拥有的已打开文件、定时器、信号量机构等。由于同一个进程内的线程共享内存和文件,所以线程之间互相通信不必调用内核,因而占用更少的系统资源。

进程与线程的比较:

1、用户空间资源的对比:



每个进程在创建时额外申请了新的内存空间以及代码段、数据段、bss段、堆、栈空间,并且初始化成父亲地址空间的值(复制),父子进程在创建后不能互相访问对方资源。

每个线程的创建时仅在用户空间申请自己的栈空间,而与其他进程共享其他地址空间(代码段、数据段、bss段和堆空间)。

2、内核空间资源对比:

我们知道,每个进程中的PCB中的mm_struct结构体来描述这个进程的地址空间,使用fork()创建的新进程与父进程的地址空间是分开的,而同一进程下创建的线程共享这一地址空间,在创建线程时,内核仍会创建一个新的pcb来标识这个线程,内核对于进程或线程的认识来源于pcb,一个进程如果不创建新的进程,可以说他是一个只有一个线程的进程,如果创建了额外的线程,原来的进程亦称为主线程。

线程不能脱离进程而独立存在,进程是操作系统管理资源的基本单位,而线程是linux系统调度的基本单元。

创建线程:

函数pthread_create()用来创建一个新的线程:

extern int pthread_create(pthread_t* _newthread,const pthread_attr_t* attr,void*(start)(void),void*arg);

第一个参数:存储线程ID,参数为指向线程ID的指针,线程ID在某个进程中是唯一的,不同进程中线程ID可能相同。

第二个参数:设置进程属性,一般设置为空

第三个参数:线程运行的代码起始地址,即在此线程中运行那段代码。。。

第四个参数:运行函数的参数地址,如果需要传多个参数,则需要使用一个包含这些参数的结构体地址。

线程创建此函数如果执行成功,返回0;失败,返回非0值。

创建线程代码:

#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>

void* pthread_run()
{
printf("process ID:%d\n,pthread ID:%lu\n",getpid(),pthread_self());
sleep(3);
return (void*)5;
}

int main()
{
pthread_t thread_id;
pthread_create(&thread_id,NULL,&pthread_run,NULL);
printf("pcrcess ID:%d\n ,the ID:%lu\n",getpid(),pthread_self());
pthread_join(thread_id,NULL);  //wait
return 0;
}


运行结果:



运行结果发现:属于同一个进程中不同线程。

线程退出与等待:

线程退出操作

a.使用return 退出,注意:不能用return 退出主线程;

b.使用pthread_exit()函数退出;

extern void pthread_exit(void* _retval);参数_retval为退出码

c.pthread_cancel函数取消该线程,线程也可自己取消自己;

退出代码:

#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>

void* pthread_run()
{
printf("process ID:%d\n,pthread ID:%lu\n",getpid(),pthread_self());
sleep(200);
//pthread_cancel(thread_id);
return (void*)5;
}

int main()
{
pthread_t thread_id;
pthread_create(&thread_id,NULL,&pthread_run,NULL);
printf("pcrcess ID:%d\n ,the ID:%lu\n",getpid(),pthread_self());
pthread_cancel(thread_id);
sleep(5);
pthread_join(thread_id,NULL);  //wait
return 0;
}




结果表明:代码原来应该等待200s,但是取消新创建的线程后,5s代码跑完。

线程的分离结合属性:

在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached),线程分离的作用:当主线程与新线程无关时,主线程无需等待,提高效率。

如果要设置某个线程为独立线程,则可调用pthread_detach()函数;

函数声明:extern int pthread_detach(pthread_t _th);

代码:

#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>

void* pthread_run()
{
printf("process ID:%d\n,pthread ID:%lu\n",getpid(),pthread_self());
sleep(200);
return (void*)5;
}

int main()
{
pthread_t thread_id;
pthread_create(&thread_id,NULL,&pthread_run,NULL);
printf("pcrcess ID:%d\n ,the ID:%lu\n",getpid(),pthread_self());
//pthread_cancel(thread_id);
pthread_detach(thread_id);
sleep(5);
pthread_join(thread_id,NULL);  //wait
return 0;
}




同样,代码在5s时间内跑完,并且在代码中没有终止线程函数,说明创建的线程已经被分离。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息