最近尝试下Linux下使用多线程开发程序,在百度文库中找到了一段比较好的范例,介绍的很全面,拿出来和大家分享。
Linux系统下的多线程遵循POSIX线程接口,称为 pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。clone()是 Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的读者可以去查看有关文档说明。下面我们展示一个最简单的多线程程序pthread_create.c。
一个重要的线程创建函数原型:
- <span style="font-size:12px;"> #include <pthread.h>
- int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);
- </span>
返回值:若是成功建立线程返回0,否则返回错误的编号
形式参数:
pthread_t *restrict tidp要创建的线程的线程id指针
const pthread_attr_t *restrict attr创建线程时的线程属性
void* (start_rtn)(void)返回值是void类型的指针函数
void *restrict arg start_rtn的行参
例程1:
功能:向新的线程传递整形值
- <span style="font-size:12px;">
- #include <stdio.h>
- #include <pthread.h>
- #include <unistd.h>
- void *create(void *arg)
- {
- int *num;
- num = (int *)arg;
- printf("create parameter is %d \n",*num);
- return (void *)0;
- }
- int main(int argc ,char *argv[])
- {
- pthread_t tidp;
- int error;
- int test=4;
- int *attr=&test;
- error=pthread_create(&tidp,NULL,create,(void *)attr);
- if(error)
- {
- printf("pthread_create is created is not created ... \n");
- return -1;
- }
- sleep(1);
- printf("pthread_create is created ...\n");
- return 0;
- }
- </span>
编译方法:
gcc -lpthread pthread_int.c -Wall
执行结果:
create parameter is 4
pthread_create is created is created ...
例程总结:
可以看出来,我们在main函数中传递的整行指针,传递到我们新建的线程函数中。
在上面的例子可以看出来我们向新的线程传入了另一个线程的int数据,线程之间还可以传递字符串或是更复杂的数据结构。
例程2:
- <span style="font-size:12px;">程序功能:向新建的线程传递字符串
- #include <pthread.h>
- #include <stdio.h>
- #include <unistd.h>
- void *create(void *arg)
- {
- char *name;
- name = (char *)arg;
- printf("The parameter passed from main function is %s \n",name);
- return (void *)0;
- }
- int main(int argc, char *argv[])
- {
- char *a="zieckey";
- int error;
- pthread_t tidp;
- error = pthread_create(&tidp, NULL, create, (void *)a);
- if(error!=0)
- {
- printf("pthread is not created.\n");
- return -1;
- }
- sleep(1);
- printf("pthread is created... \n");
- return 0;
- } </span>
编译方法:
gcc -Wall pthread_string.c -lpthread
执行结果:
The parameter passed from main function is zieckey pthread is created...
例程总结:
可以看出来main函数中的字符串传入了新建的线程中。
例程3:
- <span style="font-size:12px;"> 程序目的:验证新建立的线程可以共享进程中的数据
- #include <stdio.h>
- #include <pthread.h>
- #include <unistd.h>
- static int a=4;
- void *create(void *arg)
- {
- printf("new pthread ... \n");
- printf("a=%d \n",a);
- return (void *)0;
- }
- int main(int argc,char *argv[])
- {
- pthread_t tidp;
- int error;
- a=5;
- error = pthread_create(&tidp, NULL, create, NULL);
- if(error!=0)
- {
- printf("new thread is not create ... \n");
- return -1;
- }
- sleep(1);
- printf("new thread is created ... \n");
- return 0;
- }
- </span>
编译方法:
gcc -Wall pthread_share_data.c -lpthread
执行结果:
new pthread ...
a=5
new thread is created ...
例程总结:
可以看出来,我们在主线程更改了我们的全局变量a的值的时候,我们新建立的线程则打印出来了改变的值,可以看出可以访问线程所在进程中的数据信息。
2、线程的终止
如果进程中任何一个线程中调用exit,_Exit,或者是_exit,那么整个进程就会终止,
与此类似,如果信号的默认的动作是终止进程,那么,把该信号发送到线程会终止进程。
线程的正常退出的方式:
(1) 线程只是从启动例程中返回,返回值是线程中的退出码
(2) 线程可以被另一个进程进行终止
(3) 线程自己调用pthread_exit函数
两个重要的函数原型:
- <span style="font-size:12px;"> #include <pthread.h>
- void pthread_exit(void *rval_ptr); /*rval_ptr 线程退出返回的指针*/
- int pthread_join(pthread_t thread,void **rval_ptr); /*成功结束进程为0,否则为错误编码*/
- </span>
例程4
- <span style="font-size:12px;"> 程序目的:线程正常退出,接受线程退出的
- #include <stdio.h>
- #include <pthread.h>
- #include <unistd.h>
- void *create(void *arg)
- {
- printf("new thread is created ... \n");
- return (void *)8;
- }
- int main(int argc,char *argv[])
- {
- pthread_t tid;
- int error;
- void *temp;
- error = pthread_create(&tid, NULL, create, NULL);
- if( error )
- {
- printf("thread is not created ... \n");
- return -1;
- }
- error = pthread_join(tid, &temp);
- if( error )
- {
- printf("thread is not exit ... \n");
- return -2;
- }
- printf("thread is exit code %d \n", (int )temp);
- return 0;
- } </span>
编译方法:
gcc -Wall pthread_exit.c -lpthread
执行结果:
new thread is created ...
thread is exit code 8
例程总结:
可以看出来,线程退出可以返回线程的int数值。线程退出不仅仅可以返回线程的int数值,还可以返回一个复杂的数据结构。
例程5
- <span style="font-size:12px;"> #include <stdio.h>
- #include <pthread.h>
- #include <unistd.h>
- struct menber
- {
- int a;
- char *b;
- }
- temp = {8,"zieckey"};
- void *create(void *arg)
- {
- printf("new thread ... \n");
- return (void *)&temp;
- }
- int main(int argc,char *argv[])
- {
- int error;
- pthread_t tid;
- struct menber *c;
- error = pthread_create(&tid, NULL, create, NULL);
- if( error )
- {
- printf("new thread is not created ... \n");
- return -1;
- }
- printf("main ... \n");
- error = pthread_join(tid,(void *)&c);
- if( error )
- {
- printf("new thread is not exit ... \n");
- return -2;
- }
- printf("c->a = %d \n",c->a);
- printf("c->b = %s \n",c->b);
- sleep(1);
- return 0;
- } </span>
编译方法:
gcc -Wall pthread_return_struct.c -lpthread
执行结果:
main ...
new thread ...
c->a = 8
c->b = zieckey
例程总结:
一定要记得返回的数据结构要是在这个数据要返回的结构没有释放的时候应用, 如果数据结构已经发生变化,那返回的就不会是我们所需要的,而是脏数据
3、线程标识
函数原型:
- <span style="font-size:12px;"> #include <pthread.h>
- pthread_t pthread_self(void);
- pid_t getpid(void);
- </span>
getpid()用来取得目前进程的进程识别码,函数说明
例程6
- <span style="font-size:12px;">
- #include <stdio.h>
- #include <pthread.h>
- #include <unistd.h> /*getpid()*/
- void *create(void *arg)
- {
- printf("New thread .... \n");
- printf("This thread's id is %u \n", (unsigned int)pthread_self());
- printf("The process pid is %d \n",getpid());
- return (void *)0;
- }
- int main(int argc,char *argv[])
- {
- pthread_t tid;
- int error;
- printf("Main thread is starting ... \n");
- error = pthread_create(&tid, NULL, create, NULL);
- if(error)
- {
- printf("thread is not created ... \n");
- return -1;
- }
- printf("The main process's pid is %d \n",getpid());
- sleep(1);
- return 0;
- } </span>
编译方法:
gcc -Wall -lpthread pthread_id.c
执行结果:
Main thread is starting ...
The main process's pid is 3307
New thread ....
This thread's id is 3086347152
The process pid is 3307