1.简介程序、进程与线程
程序(Program或Procedure,港台称之为程式)是一组用计算机语言编写的命令序列的集合。程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的「程序」就称之为进程。线程是系统分配处理器时间资源的基本单元。每启动一个程序,就至少启动了一个进程。
进程(Process,台湾译作行程)是计算机中已运行程序的实体。程序本身只是指令的集合,进程才是程序(那些指令)的真正运行。进程本身不会运行,是线程的容器。线程不能单独执行,必须组成进程。一个程序至少有一个进程,一个进程至少有一个线程。
线程(Thread,台湾称执行绪)是进程中某个单一顺序的控制流,指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。多线程主要是为了节约CPU时间。
在任务管理器中查看进程和线程
线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源(线程的运行中需要使用计算机的内存资源和CPU),但它可与同属一个进程的其它线程共享进程所拥有的全部资源。通常在一个进程中可以包含若干个线程,它们可以利用进程所拥有的资源。对于进程而言,数据之间都是相互隔离的,而多线程则不同,不同的线程除了堆栈空间之外所有的数据都是共享的。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。
2.简单的多线程编程
我们可以使用函数pthread_create创建一个新的线程。
函数原型:
int pthread_create(pthread_t *thread,
pthread_attr_t *attr,
void *(*func)(void*),
void *arg);
参数: thread 指向pthread_t类型变量的指针
attr 指向pthread_attr_t类型变量的指针,或者为NULL
func 指向新线程所运行函数的指针
arg 传递给func的参数
返回值 0 成功返回
errcode 错误
我们可以使用函数pthread_join等待某进程结束。
函数原型:int pthread_join(pthread_t thread,void ** retval);
参数: thread 所等待的进程
retval 指向某存储线程返回值的变量
返回值: 0 成功返回
errorcode 错误
以上两个函数都包含在头文件pthread.h中。
Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。linux下要编译使用线程的代码,一定要记得调用pthread库。
例子1:主线和与子线程的调用
/* thread_example1.c*/
#include <stdio.h>
#include <pthread.h>
void thread(void)
{
int i;
for(i=0;i<3;i++)
printf("This is a pthread.\n");
}
int main(void)
{
pthread_t id = 0;
int i,ret;
ret=pthread_create(&id,NULL,(void *) thread,NULL); // 成功返回0,错误返回错误编号
if(ret!=0) {
printf ("Create pthread error!\n");
exit (1);
}
for(i=0;i<3;i++)
printf("This is the main process.\n");
If(id>0)
{
pthread_join(id,NULL);
id = 0;
}
return (0);
}
我们编译此程序:
#gcc thread_example1.c -lpthread -o thread_example1
运行thread_example,我们得到如下结果:
This is the main process.
This is a pthread.
This is the main process.
This is the main process.
This is a pthread.
This is a pthread.
再次运行,我们可能得到如下结果:
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
前后两次结果不一样,这是两个线程争夺CPU资源的结果。
例子2:2子线程的调用
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
void func_1(void* args)
{
while(1){
sleep(1);
printf("this is func_1!\n");
}
}
void func_2(void* args)
{
while(1){
sleep(2);
printf("this is func_2!\n");
}
}
int main()
{
pthread_t pid1, pid2;
if(pthread_create(&pid1, NULL, func_1, NULL))
{
return -1;
}
if(pthread_create(&pid2, NULL, func_2, NULL))
{
return -1;
}
while(1){
sleep(3);
}
return 0;
}
#gcc thread_example2.c -o thread_example2 -lpthread
#./thread_example2
this is func_1!
this is func_2!
this is func_1!
this is func_1!
this is func_2!
this is func_1!
this is func_1!
this is func_2!
this is func_1!
this is func_1!