进程是系统中程序执行和资源分配的基本单位,线程是系统调度的最小单位。每个进程有自己的数据段(data)、代码段(text)和堆栈段(bss)。线程通常叫做轻量的进程。线程是在共享内存空间中并发执行的多道执行路径,他们共享一个进程的资源。因为线程和进程比起来很小,所以相对来说,线程花费更少的CPU资源。
线程按照其调度者可分为用户级线程和内核级线程两种。(1)用户级线程
主要解决的是上下文切换的问题,其调度算法和调度过程全部有用户决定。
(2)内核级线程
有内核调度机制实现。
现在大多数操作系统都采用用户级线程和内核级线程并存的方法。用户级线程可与内核级线程实现“一对一”,“一对多”的对应关系。
创建线程使用pthread_create函数。在线程创建以后,就开始运行相关的线程函数。线程退出时使用函数pthread_exit,是线程的主动行为。如果进程中任何一个线程中调用exit或_exit,那么整个进程都会终止。线程的正常退出方式有:
(1) 线程从启动例程中返回
(2) 线程可以被另一个进程终止
(3) 线程自己调用pthread_exit函数
由于一个进程中的多个线程共享数据段,因此通常在线程退出后,退出线程所占用的资源并不会随线程结束而释放。所有需要pthread_join函数来等待线程结束,类似于wait系统调用。
创建线程:
#include <pthread.h>
pthread_create(pthread_t *thread,pthread_attr_t *attr,
void *(*start_routine)(void *),void *arg)
thread:线程标识符
attr:线程属性设置
start_routine:线程函数起始地址
arg:传递给start_routine的参数
退出线程:
#include <pthread.h>
pthread_exit( void *retval )
retval: pthread_exit调用者线程的返回值,可由其他函数和pthread_join来检测获取。
等待线程退出:
#include <pthread.h>
pthread_join( pthread_t *th,void **thread_return )
th:等待线程的标识符
thread_return:用户定义指针,用来存储被等待线程的返回值
代码例程:
#include <stdio.h>
#include <pthread.h>
void thread1(void)
{
int i=0;
for(i=0;i<6;i++)
{
printf("This is a pthread1.\n");
if(i==2)
pthread_exit(0); //线程退出
sleep(1);
}
}
void thread2(void)
{
int i;
for(i=0;i<3;i++)
printf("This is a pthread2.\n");
pthread_exit(0); //线程退出
}
int main(void)
{
pthread_t id1,id2;
int ret;
ret=pthread_create(&id1,NULL,(void *) thread1,NULL); //创建线程
if(ret!=0)
{
printf ("Create pthread error!\n");
exit (1);
}
ret=pthread_create(&id2,NULL,(void *) thread2,NULL); //创建线程
if(ret!=0)
{
printf ("Create pthread error!\n");
exit (1);
}
pthread_join(id1,NULL); //等待响应线程退出
pthread_join(id2,NULL); //等待响应线程退出
exit (0);
}
线程传值(int,string,struct等数据类型):
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *create(void *arg)
{
int *num;
num=(int *)arg;
printf("create parameter is %d \n",*num);
return (void *)0;
}
int main(int argc ,char *argv[])
{
pthread_t tidp;
int error;
int test=4;
int *attr=&test;
error=pthread_create(&tidp,NULL,create,(void *)attr);
if(error)
{
printf("pthread_create is created is not created ... \n");
return -1;
}
sleep(1);
printf("pthread_create is created ...\n");
return 0;
}
创建一个线程的默认状态是joinable,如果一个线程结束运行但没有被pthread_join上面的线程传值程序就是,则这个线程的状态类似于进程的僵尸进程永远驻留,也就是有一部分资源没有被回收,所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收期资源。但是在调用pthread_join后,如果线程没有运行结束,调用者会被阻塞,有些情况下我们并不希望如此,比如在WEB服务器中当主线程为每个新来的请求连接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而主色,这是可以在子线程中加入代码pthread_detach(pthread_self());
pthread_detach(thread_id)
这是一个非阻塞,可立即返回。
将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void thread1(void)
{
int i = 0;
printf("thread2 id is:%u\n",(unsigned int)pthread_self());
for(i=0;i<6;i++)
{
printf("this is a pthread1\n");
if(i==2)
{
pthread_exit(0);
}
sleep(1);
}
}
void thread2(void)
{
int i;
printf("thread2 id is:%u\n",(unsigned int)pthread_self());
for(i=0;i<3;i++)
{
printf("this is a pthread2\n");
}
pthread_exit("exit from thread2");
}
int main(int argc,char **argv)
{
pthread_t id1,id2;
int ret;
void* thread_result;
ret = pthread_create(&id1,NULL,(void*)thread1,NULL);
if(ret!=0)
{
perror("create pthread1 error");
exit(1);
}
pthread_detach(id1);
ret = pthread_create(&id2,NULL,(void*)thread2,NULL);
if(ret!=0)
{
perror("create pthread2 error");
exit(1);
}
pthread_join(id2,&thread_result);
printf("%s\n",(char *)thread_result);
sleep(10);
exit(0);
}