多线程编程

一、线程理论基础

  线程(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 run
11     }
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

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。