首页 > 代码库 > 多线程编程

多线程编程

一、线程理论基础

  线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。传统的Unix也支持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多线程就意味着多进程。现在,多线程技术已经被许多操作系统所支持,包括Windows/NT,当然,也包括Linux。

1、为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?我们首先必须回答这些问题。  

  使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。  

  使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。  

2、多线程程序作为一种多任务、并发的工作方式,还有以下的优点:  

(1) 提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的情况。  

(2)使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。  

(3)改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。

3、Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。

注:一个线程所包含的信息呈现出了它在一个进程中的执行环境,它们包括线程ID,线程栈,时刻优先级和策略(a scheduling priority and policy),信号屏蔽字,error变量以及线程相关的特定数据(线程私有数据)。在一个进程中几乎所有的东西都是可以共享的,包括代码段,全局变量以及堆、栈,还包括文件描述符等。一个线程的线程ID是用于在进程中唯一确定的标识,和进程ID不同,它只有在该线程所在的进程中才有意义。

二、多线程程序设计

1、创建线程 

1 #include <pthread.h>2 int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void), void *restrict arg);  

参数:tidp指线程id;attr是线程属性,默认时可赋值为空;start_rtn是一个函数指针,线程创建成功后,该函数将作为线程的入口函数开始运行;arg是传递给该线程函数start_rtn的参数。

返回值:创建成功,返回0,并将新创建线程的标识符存放在由tidp指向的地址;若失败,则返回一个非负值。

注:因为pthread的库不是Linux系统的库,所以在进行编译的时候要加上 -lpthread.

 1 #include <stdio.h> 2 #include <pthread.h> 3  4 void *myThread1(void) 5 { 6     int i; 7     for (i=0; i<100; i++) 8     { 9         printf("This is the 1st pthread,created by zieckey.\n");10         sleep(1);//Let this thread to sleep 1 second,and then continue to run11     }12 }13 14 void *myThread2(void)15 {16     int i;17     for (i=0; i<100; i++)18     {19         printf("This is the 2st pthread,created by zieckey.\n");20         sleep(1);21     }22 }23 24 int main()25 {26     int i=0, ret=0;27     pthread_t id1,id2;28     29     /*创建线程1*/30     ret = pthread_create(&id1, NULL, (void*)myThread1, NULL);31     if (ret)32     {33         printf("Create pthread error!\n");34         return 1;35     }36     37     /*创建线程2*/38     ret = pthread_create(&id2, NULL, (void*)myThread2, NULL);39     if (ret)40     {41         printf("Create pthread error!\n");42         return 1;43     }44     45     pthread_join(id1, NULL);46     pthread_join(id2, NULL);47     48     return 0;49 }
thread_create.c

编译:gcc thread_create.c -lpthread -o thread_create

传递整型:

 1 #include <stdio.h> 2 #include <pthread.h> 3 #include <unistd.h> 4  5 void *create(void *arg) 6 { 7     int *num; 8     num=(int *)arg; 9     printf("create parameter is %d \n",*num);10     return (void *)0;11 }12 int main(int argc ,char *argv[])13 {14     pthread_t tidp;15     int error;16     17     int test=4;18     int *attr=&test;19     20     error=pthread_create(&tidp,NULL,create,(void *)attr);21 22     if(error)23     {24         printf("pthread_create is not created ... \n");25         return -1;26     }27     sleep(1);28     printf("pthread_create is created ...\n");29     return 0;        30 }
thread_int.c

传递字符串:

 1 #include <pthread.h> 2 #include <stdio.h> 3 #include <unistd.h> 4  5 void *create(void *arg) 6 { 7     char *name; 8     name=(char *)arg; 9     printf("The parameter passed from main function is %s  \n",name);10     return (void *)0;11 }12 13 int main(int argc, char *argv[])14 {15     char *a="zieckey";16     int error;17     pthread_t tidp;18 19     error=pthread_create(&tidp, NULL, create, (void *)a);20 21     if(error!=0)22     {23         printf("pthread is not created.\n");24         return -1;25     }26     sleep(1);27     printf("pthread is created... \n");28     return 0;29 }    
thread_string.c

传递结构:

 1 #include <stdio.h> 2 #include <pthread.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5  6 struct menber 7 { 8     int a; 9     char *s;10 };11 12 void *create(void *arg)13 {14     struct menber *temp;15     temp=(struct menber *)arg;16     printf("menber->a = %d  \n",temp->a);17     printf("menber->s = %s  \n",temp->s);18     return (void *)0;19 }20 21 int main(int argc,char *argv[])22 {23     pthread_t tidp;24     int error;25     struct menber *b;26     b=(struct menber *)malloc( sizeof(struct menber) );27     b->a = 4;28     b->s = "zieckey";29 30     error = pthread_create(&tidp, NULL, create, (void *)b);31 32     if( error )33     {34         printf("phread is not created...\n");35         return -1;36     }37     sleep(1);38     printf("pthread is created...\n");39     return 0;40 }
thread_struct.c

共享数据:

 1 #include <stdio.h> 2 #include <pthread.h> 3 #include <unistd.h> 4  5 //static int a=4; 6  7 int a = 1; 8  9 void *create(void *arg)10 {11     printf("new pthread ... \n");12     printf("a=%d  \n",a);13     return (void *)0;14 }15 16 int main(int argc,char *argv[])17 {18     pthread_t tidp;19     int error;20     21     int a=5;22 23     printf("a = %d\n",a);24     25     //error=pthread_create(&tidp, NULL, create, NULL);26 27     if(error!=0)28     {29         printf("new thread is not create ... \n");30         return -1;31     }32     33     sleep(1);34     35     printf("new thread is created ... \n");36     return 0;37 }
thread_share.c

2、终止线程

如果进程中任何一个线程中调用exit或_exit,那么整个进程都会终止。线程正常终止的三种方式如下:

(1) 线程从线程入口函数处返回,其返回值将是该线程的终止状态。

(2)该线程被相同进程中的其他线程所取消。

(3)线程调用pthread_exit函数终止当前线程,该函数的参数将被作为终止状态。

1 #include <pthread.h>2 void pthread_exit(void *rval_ptr);

功能:终止调用线程。

参数:rval_ptr 是线程退出返回值的指针。

 1 #include <stdio.h> 2 #include <pthread.h> 3 #include <unistd.h> 4  5 void *create(void *arg) 6 { 7     printf("new thread is created ... \n"); 8     return (void *)8; 9     //pthread_exit((void *)8);10     //eixt(0);11 }12 13 int main(int argc,char *argv[])14 {15     pthread_t tid;16     int error;17     void *temp;18 19     error = pthread_create(&tid, NULL, create, NULL);20     printf("main thread!\n");21 22     if(error)23     {24         printf("thread is not created ... \n");25         return -1;26     }27     error = pthread_join(tid, &temp);28 29     if(error)30     {31         printf("thread is not exit ... \n");32         return -2;33     }34     35     printf("thread is exit code %d \n", (int )temp);36     return 0;37 }
thread_exit.c

 

多线程编程