进程是系统中程序执行和资源分配的基本单位,每个进程都有自己的数据段,代码段和堆栈段,这就使得进程在进行切换等操作时需要有上下文切换动作,为了减少上下文切换开销,进程在演化过程中出现了另外一个概念,就是线程。它是一个进程内的基本调度单位,也可以称为轻量级进程。
使用多线程是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。
另外,使用多线程可以方便线程间的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。
多线程程序同样具有作为一种多任务、并发的工作方式的优点:
1) 提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)启动一个新的线程去执行,可以避免这种瓶颈对系统响应速度的影响。
2) 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
3) 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。
(二) 多线程编程
1、线程的创建与退出
创建线程实际上就是确定调用该线程的函数入口点,通常使用函数: pthread_create
在线程创建后,就开始运行相关的线程函数,在该函数运行完后,线程也就退出了,若想在线程函数结束之前提前退出,可使用函数: pthread_exit
其中:pthread_create函数原型为:
int pthread_create(pthread_t *thread,pthread_attr_t *attr,void*(*start_routine)(void*),void *arg)
参数介绍:thread:线程标识符
attr:线程属性设置,NULL默认为joinable属性,线程在执行完毕后不会立即被Linux清除,如果函数有返回值,其返回值可以通过调用函数pthread_join()得到。
*start_routine:指向新线程所要执行的函数指针。
arg:传递给新线程的参数。
pthread_exit函数原型: void pthread_exit(void *retval)
参数介绍: Retval:调用pthread_exit()线程函数的返回值,可由函数:pthread_join来检索获取。
pthread_join函数原型:int pthread_join(pthread_t th,void **thread_reaturn)
参数介绍: th:等待线程的标识符。
thread_return:用户定义的指针,当不为NULL时,用来存储被等待线程的返回值。
2、上机实验举例
/***expriment.c****/
# include<stdio.h>
#i nclude<pthread.h>
/***线程一***/
void task1(void)
{
int i=0;
for(i=0;i<3;i++)
{
printf("This is thread1.\n");
if(i==2)
pthread_exit(0);
sleep(1);
}
}
/***线程二***/
void task2(void)
{
int i;
for(i=0;i<3;i++)
printf("This is thread2.\n“)
pthread_exit(0);
}
int main(void)
{
pthread_t id1,id2;
int i,ret;
/***创建线程一***/
ret=pthread-create(&id1,NULL,(void *) task1,NULL );
if (ret!=0)
{
printf("create pthreaed error!\n“);
exit(1);
}
/***创建线程二***/
ret=pthread_create(&id2,NULL,(void *) task2,NULL)
if(ret!=0)
{
printf(" create pthread error!\n");
exit(1);
}
/***等待线程结束***/
pthread_join(id1,NULL);
pthread_join(id2,NULL);
exit(0);
}
以下是实验运行结果:
[root@Caiwm expriment]# ./expriment
This is thread1.
This is thread2.
This is thread2.
This is thread2.
This is thread1.
This is thread1.