linux线程篇之(一):线程的创建与应用
时间:2010-11-09 来源:andyluo324324
#include<stdio.h>
#include<pthread.h> void thread1(void)//线程1
{
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)//线程2
{
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 i,ret;
ret=pthread_create(&id1,NULL,(void *)thread1,NULL);//创建线程1
if(ret!=0)
{
printf("create pthread error !\n");
exit(1);
}
ret=pthread_create(&id2,NULL,(void *)thread2,NULL);//创建线程2
if(ret!=0)
{
printf("create pthread error !\n");
exit(1);
}
pthread_join(id1,NULL);//等待进程结束
pthread_join(id2,NULL);
exit(0);
} /*-------------------------------------------------------
1.进程是系统中程序执行和资源分配的基本单位。每个进程都拥有自己的数据段,代码段
和堆栈段,这就造成了进程在进行切换等操作时都需要有比较负责的上下文切换等动作.为
了进一步减少处理机的空转时间支持多个处理器和减少上下文切换开销,进程在演化中出现
了另一个概念--线程。它是一个进程内的基本调度单位,也可以称为轻量级进程。线程是在
供享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。因
此,大大减少了上下文切换的开销。
2.同进程一样,线程也将相关的变量值放在线程控制表内。一个进程可以有多个线程,也就是
有多个线程控制表及堆栈寄存器,但却共享一个用户地址空间。由于线程共享了进程的资源和
地址空间,因此,任何线程对系统资源的操作都会给其他线程带来影响,因此,多线程中的同步
就是非常重要的问题了。
3.线程分类
线程按照其调度者可以分为用户级线程和核心级线程两种。
1)用户级线程
用户级线程主要解决的是上下文切换的问题,它的调度算法和调度过程全部由用户自行选择决定,
在运行时不需要特定的内核支持。在这里,操作系统往往会提供一个用户空间的线程库,该线程
库提供了线程的创建,调度,撤消等功能,而内核依然仅对进程进行管理。
如果一个进程中的某个线程调用了一个阻塞的系统调用,那么该进程包括该进程中的其他所有
线程也同时被阻塞。这种用户级的重要缺点是在一个进程中的多个线程的调度中无法发挥多处理器
的优势。
2)核心级线程
这种线程允许进程中的线程按照同一相对优先调度方法进行调度,这样就可以发挥多处理器的
并发优势。
现在大多数系统都采用用户级线程与核心进程并存的方法。一个用户级线程可以对应一个或几
个核心级线程,也就是"一对一"或"多对一"模型。这样既可满足多处理机系统的需要,也可以最大
限度地减少调度开销。
4.线程的创建和退出
1)函数说明
创建线程实际上就是确定调用该线程函数的入口点,这里通常使用的函数是pthread_creat.
在线程创建以后,就开始运行相关的线程函数,在该函数运行完之后,该线程也就退出了,这也
是线程退出的一种方法。另一种退出线程的方法是使用函数pthread_exit,这是线程的主动
行为。在使用线程函数时,不要随意使用exit退出函数进行出错处理,由于exit的作用是使
调用进程终止,往往一个进程包含多个线程,因此,在使用exit之后,该进程中的所以线程都
终止了。因此,在线程中就可以使用pthread_exit来替代进程中的exit.
2)由于一个进程中的多个线程是共享数据段的,因此通常在现成退出之后,退出线程所占用的
资源并不会随着线程的终止而得到释放。正如进程之间可以用wait()系统调用来同步终止并释放
资源一样,线程之间也有类似机制,那就是 pthread_join()函数。pthread_join()可以用于将
当前线程挂起,等待线程的结束。这个函数是一个线程阻塞的函数,调用它的函数将一直等待
到被等待的线程结束为止,当函数返回时,被等待线程的资源就被收回。
3)pthread_creat函数语法要点
I:所需要的头文件:#include<pthread.h>
II:函数原型
int pthread_create((pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void *),
void *arg))
III:函数的输入参数
thread:线程标识符
attr:线程属性设置
start_routine:线程函数的起始地址
arg:传递给start_routine的参数
IIII:函数返回值
成功:0
出错:-1
4)pthread_exit函数的语法特点
I:所需要的头文件:#incldue<pthread.h>
II:函数原型
void pthread_exit(void *retval)
III:函数输入参数
retval:pthread_exit()调用者线程的返回值,可由其他函数如pthread_jion来检索获取
5)pthread_join函数语法特点
I:所需要的头文件:#include<pthread.h>
II:函数原型
int pthread_join((pthread_t th,void **thread_return))
III:函数的输入参数
th:等待线程的标示符
thread_return:用户定义的指针,用来存储被等待线程的返回值(不为NULL时)
IIII:函数返回值
成功:0
出错:-1
5.实验:
1)因为pthread的库不是linux系统的库,所以在进行编译的时候要加上
-lpthread
eg:gcc filename -lpthread
2)
[root@localhost the_ninth_step]# gcc thread.c -lpthread -o thread
[root@localhost the_ninth_step]# ./thread
this is a pthread1.
this is a pthread2.
this is a pthread2.
this is a pthread2.
------------------------------------------------------*/
#include<pthread.h> void thread1(void)//线程1
{
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)//线程2
{
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 i,ret;
ret=pthread_create(&id1,NULL,(void *)thread1,NULL);//创建线程1
if(ret!=0)
{
printf("create pthread error !\n");
exit(1);
}
ret=pthread_create(&id2,NULL,(void *)thread2,NULL);//创建线程2
if(ret!=0)
{
printf("create pthread error !\n");
exit(1);
}
pthread_join(id1,NULL);//等待进程结束
pthread_join(id2,NULL);
exit(0);
} /*-------------------------------------------------------
1.进程是系统中程序执行和资源分配的基本单位。每个进程都拥有自己的数据段,代码段
和堆栈段,这就造成了进程在进行切换等操作时都需要有比较负责的上下文切换等动作.为
了进一步减少处理机的空转时间支持多个处理器和减少上下文切换开销,进程在演化中出现
了另一个概念--线程。它是一个进程内的基本调度单位,也可以称为轻量级进程。线程是在
供享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。因
此,大大减少了上下文切换的开销。
2.同进程一样,线程也将相关的变量值放在线程控制表内。一个进程可以有多个线程,也就是
有多个线程控制表及堆栈寄存器,但却共享一个用户地址空间。由于线程共享了进程的资源和
地址空间,因此,任何线程对系统资源的操作都会给其他线程带来影响,因此,多线程中的同步
就是非常重要的问题了。
3.线程分类
线程按照其调度者可以分为用户级线程和核心级线程两种。
1)用户级线程
用户级线程主要解决的是上下文切换的问题,它的调度算法和调度过程全部由用户自行选择决定,
在运行时不需要特定的内核支持。在这里,操作系统往往会提供一个用户空间的线程库,该线程
库提供了线程的创建,调度,撤消等功能,而内核依然仅对进程进行管理。
如果一个进程中的某个线程调用了一个阻塞的系统调用,那么该进程包括该进程中的其他所有
线程也同时被阻塞。这种用户级的重要缺点是在一个进程中的多个线程的调度中无法发挥多处理器
的优势。
2)核心级线程
这种线程允许进程中的线程按照同一相对优先调度方法进行调度,这样就可以发挥多处理器的
并发优势。
现在大多数系统都采用用户级线程与核心进程并存的方法。一个用户级线程可以对应一个或几
个核心级线程,也就是"一对一"或"多对一"模型。这样既可满足多处理机系统的需要,也可以最大
限度地减少调度开销。
4.线程的创建和退出
1)函数说明
创建线程实际上就是确定调用该线程函数的入口点,这里通常使用的函数是pthread_creat.
在线程创建以后,就开始运行相关的线程函数,在该函数运行完之后,该线程也就退出了,这也
是线程退出的一种方法。另一种退出线程的方法是使用函数pthread_exit,这是线程的主动
行为。在使用线程函数时,不要随意使用exit退出函数进行出错处理,由于exit的作用是使
调用进程终止,往往一个进程包含多个线程,因此,在使用exit之后,该进程中的所以线程都
终止了。因此,在线程中就可以使用pthread_exit来替代进程中的exit.
2)由于一个进程中的多个线程是共享数据段的,因此通常在现成退出之后,退出线程所占用的
资源并不会随着线程的终止而得到释放。正如进程之间可以用wait()系统调用来同步终止并释放
资源一样,线程之间也有类似机制,那就是 pthread_join()函数。pthread_join()可以用于将
当前线程挂起,等待线程的结束。这个函数是一个线程阻塞的函数,调用它的函数将一直等待
到被等待的线程结束为止,当函数返回时,被等待线程的资源就被收回。
3)pthread_creat函数语法要点
I:所需要的头文件:#include<pthread.h>
II:函数原型
int pthread_create((pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void *),
void *arg))
III:函数的输入参数
thread:线程标识符
attr:线程属性设置
start_routine:线程函数的起始地址
arg:传递给start_routine的参数
IIII:函数返回值
成功:0
出错:-1
4)pthread_exit函数的语法特点
I:所需要的头文件:#incldue<pthread.h>
II:函数原型
void pthread_exit(void *retval)
III:函数输入参数
retval:pthread_exit()调用者线程的返回值,可由其他函数如pthread_jion来检索获取
5)pthread_join函数语法特点
I:所需要的头文件:#include<pthread.h>
II:函数原型
int pthread_join((pthread_t th,void **thread_return))
III:函数的输入参数
th:等待线程的标示符
thread_return:用户定义的指针,用来存储被等待线程的返回值(不为NULL时)
IIII:函数返回值
成功:0
出错:-1
5.实验:
1)因为pthread的库不是linux系统的库,所以在进行编译的时候要加上
-lpthread
eg:gcc filename -lpthread
2)
[root@localhost the_ninth_step]# gcc thread.c -lpthread -o thread
[root@localhost the_ninth_step]# ./thread
this is a pthread1.
this is a pthread2.
this is a pthread2.
this is a pthread2.
------------------------------------------------------*/
相关阅读 更多 +