Linux系统下的多线程遵循POSIX线程接口,称为 pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux 下pthread的实现是通过系统调用clone()来实现的。clone()是 Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的读者可以去查看有关文档说明。下面我们展示一个最简单的 多线程程序 pthread_create.c。

一个重要的线程创建函数原型:
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);

返回值:若是成功建立线程返回0,否则返回错误的编号
形式参数:
                pthread_t *restrict tidp 要创建的线程的线程id指针
                const pthread_attr_t *restrict attr 创建线程时的线程属性
                void* (start_rtn)(void) 返回值是void类型的指针函数
                void *restrict arg   start_rtn的行参
                
例程1:                               
    功能:创建一个简单的线程
    程序名称:pthread_create.c

代码如下:

[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include <pthread.h>
  3. void *mythread1(void)
  4. {
  5. int i;
  6. for(i = 0; i < 10; i++)
  7. {
  8. printf("This is the 1st pthread,created by xiaoqiang!\n");
  9. sleep(1);
  10. }
  11. }
  12. void *mythread2(void)
  13. {
  14. int i;
  15. for(i = 0; i < 10; i++)
  16. {
  17. printf("This is the 2st pthread,created by xiaoqiang!\n");
  18. sleep(1);
  19. }
  20. }
  21. int main(int argc, const char *argv[])
  22. {
  23. int i = 0;
  24. int ret = 0;
  25. pthread_t id1,id2;
  26. ret = pthread_create(&id1, NULL, (void *)mythread1,NULL);
  27. if(ret)
  28. {
  29. printf("Create pthread error!\n");
  30. return 1;
  31. }
  32. ret = pthread_create(&id2, NULL, (void *)mythread2,NULL);
  33. if(ret)
  34. {
  35. printf("Create pthread error!\n");
  36. return 1;
  37. }
  38. pthread_join(id1,NULL);
  39. pthread_join(id2,NULL);
  40. return 0;
  41. }

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/thread$ vi thread1.c
  2. fs@ubuntu:~/qiang/thread$ gcc -o thread1 thread1.c -lpthread
  3. fs@ubuntu:~/qiang/thread$ ./thread1
  4. This is the 2st pthread,created by xiaoqiang!
  5. This is the 1st pthread,created by xiaoqiang!
  6. This is the 2st pthread,created by xiaoqiang!
  7. This is the 1st pthread,created by xiaoqiang!
  8. This is the 2st pthread,created by xiaoqiang!
  9. This is the 1st pthread,created by xiaoqiang!
  10. This is the 2st pthread,created by xiaoqiang!
  11. This is the 1st pthread,created by xiaoqiang!
  12. This is the 2st pthread,created by xiaoqiang!
  13. This is the 1st pthread,created by xiaoqiang!
  14. This is the 2st pthread,created by xiaoqiang!
  15. This is the 1st pthread,created by xiaoqiang!
  16. This is the 1st pthread,created by xiaoqiang!
  17. This is the 2st pthread,created by xiaoqiang!
  18. This is the 2st pthread,created by xiaoqiang!
  19. This is the 1st pthread,created by xiaoqiang!
  20. This is the 1st pthread,created by xiaoqiang!
  21. This is the 2st pthread,created by xiaoqiang!
  22. This is the 2st pthread,created by xiaoqiang!
  23. This is the 1st pthread,created by xiaoqiang!
  24. fs@ubuntu:~/qiang/thread$

两个线程交替执行。
另外,因为pthread的库不是linux系统的库,所以在进行编译的时候要加上-lpthread,否则编译不过,会出现下面错误
thread_test.c: 在函数 ‘create’ 中:
thread_test.c:7: 警告: 在有返回值的函数中,程序流程到达函数尾
/tmp/ccOBJmuD.o: In function `main':thread_test.c:(.text+0x4f):对‘pthread_create’未定义的引用
collect2: ld 返回 1
此例子介绍了创建线程的方法

下面例子介绍向线程传递参数。
例程2:
功能:向新的线程传递整形值
程序名称:pthread_int.c

代码如下:

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

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/thread$ vi thread2.c
  2. fs@ubuntu:~/qiang/thread$ gcc -o thread2 thread2.c -lpthread
  3. fs@ubuntu:~/qiang/thread$ ./thread2
  4. Create parameter is 4
  5. Pthread_create is created..
  6. fs@ubuntu:~/qiang/thread$

例程总结:
    可以看出来,我们在main函数中传递的整行指针,传递到我们新建的线程函数中。

在上面的例子可以看出来我们向新的线程传入了另一个线程的int数据,线程之间还可以传递字符串或是更复杂的数据结构。
例程3:
程序功能:向新建的线程传递字符串
程序名称:pthread_string.c
代码如下:

[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include <pthread.h>
  3. void *create(char *arg)
  4. {
  5. char *str;
  6. str = arg;
  7. printf("The parameter passed from main is %s\n",str);
  8. return (void *)0;
  9. }
  10. int main()
  11. {
  12. int error;
  13. pthread_t id1;
  14. char *str1 = "Hello ,xiaoqiang!";
  15. char *attr = str1;
  16. error = pthread_create(&id1, NULL, create, (void *)attr);
  17. if(error != 0)
  18. {
  19. printf("This pthread is not created!\n");
  20. return -1;
  21. }
  22. sleep(1);
  23. printf("pthread is created..\n");
  24. return 0;
  25. }

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/thread$ ./thread3
  2. The parameter passed from main is Hello ,xiaoqiang!
  3. pthread is created..
  4. fs@ubuntu:~/qiang/thread$

例程总结:
可以看出来main函数中的字符串传入了新建的线程中。

例程4:
程序功能:向新建的线程传递字符串
程序名称:pthread_struct.c

代码如下:

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

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/thread$ vi thread4.c
  2. fs@ubuntu:~/qiang/thread$ gcc -o thread4 thread4.c -lpthread
  3. fs@ubuntu:~/qiang/thread$ ./thread4
  4. menber->a = 1
  5. menber->s = xiaoqiang!
  6. pthread is created!
  7. fs@ubuntu:~/qiang/thread$

例程总结:
    可以看出来main函数中的一个结构体传入了新建的线程中。
    线程包含了标识进程内执行环境必须的信息。他集成了进程中的所有信息都是对线程进行共享的,包括文本程序、程序的全局内存和堆内存、栈以及文件描述符

例程5:
程序目的:验证新建立的线程可以共享进程中的数据
程序名称:pthread_share.c

代码如下:

[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include <pthread.h>
  3. static int a = 5;
  4. void *create(void *arg)
  5. {
  6. printf("New pthread...\n");
  7. printf("a = %d\n",a);
  8. return (void *)0;
  9. }
  10. int main(int argc, const char *argv[])
  11. {
  12. int error;
  13. pthread_t id1;
  14. error = pthread_create(&id1, NULL, create, NULL);
  15. if(error != 0)
  16. {
  17. printf("new thread is not created!\n");
  18. return -1;
  19. }
  20. sleep(1);
  21. printf("New thread is created...\n");
  22. return 0;
  23. }

结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/thread$ vi thread5.c
  2. fs@ubuntu:~/qiang/thread$ gcc -o thread5 thread5.c -lpthread
  3. fs@ubuntu:~/qiang/thread$ ./thread5
  4. New pthread...
  5. a = 5
  6. New thread is created...
  7. fs@ubuntu:~/qiang/thread$

例程总结:
可以看出来,我们在主线程更改了我们的全局变量a的值的时候,我们新建立的线程则打印出来了改变的值,可以看出可以访问线程所在进程中的数据信息。

2、线程的终止
如果进程中任何一个线程中调用exit,_Exit,或者是_exit,那么整个进程就会终止,
与此类似,如果信号的默认的动作是终止进程,那么,把该信号发送到线程会终止进程。
线程的正常退出的方式:
(1) 线程只是从启动例程中返回,返回值是线程中的退出码
(2) 线程可以被另一个进程进行终止
(3) 线程自己调用pthread_exit函数

两个重要的函数原型:

[cpp] view plaincopy
  1. include <pthread.h>
  2. void pthread_exit(void *rval_ptr);
  3. /*rval_ptr 线程退出返回的指针*/
  4. int pthread_join(pthread_t thread,void **rval_ptr);
  5. /*成功结束进程为0,否则为错误编码*/
pthread_join使一个线程等待另一个线程结束。
代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。
头文件 : #include <pthread.h>
函数定义: int pthread_join(pthread_t thread, void **retval);
描述 :pthread_join()函数,以阻塞的方式等待thread指定的线程结束。当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回。并且thread指定的线程必须是joinable的。
参数 :thread: 线程标识符,即线程ID,标识唯一线程。retval: 用户定义的指针,用来存储被等待线程的返回值。
返回值 : 0代表成功。 失败,返回的则是错误号。

例程6
程序目的:线程正常退出,接受线程退出的返回码
程序名称:pthread_exit.c
执行代码如下:

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

执行结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/thread$ vi thread6.c
  2. fs@ubuntu:~/qiang/thread$ gcc -o thread6 thread6.c -lpthread
  3. fs@ubuntu:~/qiang/thread$ ./thread6
  4. new thread is created ...
  5. thread is exit code 0
  6. fs@ubuntu:~/qiang/thread$

例程总结:
可以看出来,线程退出可以返回线程的int数值。

线程退出不仅仅可以返回线程的int数值,还可以返回一个复杂的数据结构

例程7
程序目的:线程结束返回一个复杂的数据结构
代码如下:
[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <unistd.h>
  4. struct menber
  5. {
  6. int a;
  7. char *b;
  8. }temp={8,"xiaoqiang"};
  9. void *create(void *arg)
  10. {
  11. printf("new thread ... \n");
  12. return (void *)&temp;
  13. }
  14. int main(int argc,char *argv[])
  15. {
  16. int error;
  17. pthread_t tid;
  18. struct menber *c;
  19. error = pthread_create(&tid, NULL, create, NULL);
  20. if( error )
  21. {
  22. printf("new thread is not created ... \n");
  23. return -1;
  24. }
  25. printf("main ... \n");
  26. error = pthread_join(tid,(void *)&c);
  27. if( error )
  28. {
  29. printf("new thread is not exit ... \n");
  30. return -2;
  31. }
  32. printf("c->a = %d  \n",c->a);
  33. printf("c->b = %s  \n",c->b);
  34. sleep(1);
  35. return 0;
  36. }
执行结果如下:
[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/thread$ gcc -o thread7 thread7.c -lpthread
  2. fs@ubuntu:~/qiang/thread$ ./thread7
  3. main ...
  4. new thread ...
  5. c->a = 8
  6. c->b = xiaoqiang
  7. fs@ubuntu:~/qiang/thread$
例程总结:
一定要记得返回的数据结构要是在这个数据要返回的结构没有释放的时候应用,如果数据结构已经发生变化,那返回的就不会是我们所需要的,而是脏数据。
3、线程标识
      函数原型:
#include <pthread.h>
pthread_t pthread_self(void);
pid_t getpid(void);
    getpid()用来取得目前进程的进程识别码,函数说明

例程8
程序目的:实现在新建立的线程中打印该线程的id和进程id

代码如下:
[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <unistd.h> /*getpid()*/
  4. void *create(void *arg)
  5. {
  6. printf("New thread .... \n");
  7. printf("This thread's id is %u  \n", (unsigned int)pthread_self());
  8. printf("The process pid is %d  \n",getpid());
  9. return (void *)0;
  10. }
  11. int main(int argc,char *argv[])
  12. {
  13. pthread_t tid;
  14. int error;
  15. printf("Main thread is starting ... \n");
  16. error = pthread_create(&tid, NULL, create, NULL);
  17. if(error)
  18. {
  19. printf("thread is not created ... \n");
  20. return -1;
  21. }
  22. printf("The main process's pid is %d  \n",getpid());
  23. sleep(1);
  24. return 0;
  25. }
  26. <span style="font-family:Arial;BACKGROUND-COLOR: #ffffff"></span>
执行结果如下:
[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/thread$ gcc -o thread8 thread8.c -lpthread
  2. fs@ubuntu:~/qiang/thread$ ./thread8
  3. Main thread is starting ...
  4. The main process's pid is 4955
  5. New thread ....
  6. This thread's id is 3075853120
  7. The process pid is 4955
  8. fs@ubuntu:~/qiang/thread$

Linux多线程编程实例解析相关推荐

  1. Linux下多线程编程实例解析

    提到线程,不得不让人想起进程,所以还是先写下进程与线程的区别吧! 一.进程与线程的区别 进程是程序执行的一个实例,进程有其自己独立的地址空间.一个线程可以含有多个线程,这也是为了提高系统资源利用率,线 ...

  2. Linux 多线程编程 实例 1

    子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码. #include <pthread.h> ...

  3. linux c编程项目实例,Linux c编程实例_例子

    例一:字符与整型变量的实现 #include int main() { int c1,c2; char c3; c1='a'-'A'; c2='b'-'B'; c3='c'-; printf(&quo ...

  4. linux c多进程多线程,linux下的C\C++多进程多线程编程实例详解

    linux下的C\C++多进程多线程编程实例详解 1.多进程编程 #include #include #include int main() { pid_t child_pid; /* 创建一个子进程 ...

  5. linux线程 ppt,Linux多线程编程多核编程.ppt

    <Linux多线程编程多核编程.ppt>由会员分享,可在线阅读,更多相关<Linux多线程编程多核编程.ppt(28页珍藏版)>请在装配图网上搜索. 1.Linux多线程编程, ...

  6. 多核程序设计 linux,多核程序设计Linux多线程编程.ppt

    Linux多线程编程,IEEE POSIX 标准 p1003.1c (Pthreads) 定义了处理线程的一系列C 语言类型的API. 在Linux中,线程一般被认为是"轻量级的进程&quo ...

  7. Linux多线程编程---线程间同步(互斥锁、条件变量、信号量和读写锁)

    本篇博文转自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了 ...

  8. python程序实例讲解_python入门编程实例 python入门编程实例解析

    python入门编程实例 python入门编程实例解析 python入门编程实例及解析: 题目:有1.2.3.4四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 程序分析:可填在百位.十 ...

  9. C#多线程编程实例 线程与窗体交互

    C#多线程编程实例 线程与窗体交互 代码: public partial class Form1 : Form{//声明线程数组Thread[] workThreads = new Thread[10 ...

最新文章

  1. 【ACM】杭电OJ 2057
  2. vim编辑二进制文件
  3. spring_Spring Boot应用程序浪费了内存
  4. Windows核心编程 第四章 进程(上)
  5. python笔记:深拷贝与浅拷贝
  6. r生成新的dataframe_2020-08-11R语言中dataframe与list的转换方法
  7. .NET 应用如何优雅的做功能开关(Feature Flag)
  8. linux系统怎么删除打印机,解决LINUX ES3.0下想指定打印机和用户的删除打印作业的问题...
  9. Dockerfile 中的 CMD 和 ENTRYPOINT 有什么区别
  10. java实现所有括号组合的遍历_括号正确嵌套问题的实现(Java)
  11. 同一个字体,不同平台完全不同
  12. 关于Select option默认选中及查询后选项值保留的问题
  13. fcm算法的MATLAB实现
  14. chromeos java安装_谷歌最新系统ChromeOS安装体验,酷!
  15. 任天堂如何通过旧技术赢得胜利
  16. 设计一个高性能三维渲染服务器,最强大脑-CATIA飞机协同设计制造工作站配置方案2016...
  17. Unknown host 'dl.google.com'. You may need to adjust the proxy settings in Gradle.
  18. ML笔记:预训练(pre-training/trained)与微调(fine tuning)
  19. 15_Elasticsearch 内部原理详细解析(下篇)
  20. MySQL报错:Duplicate entry ‘xxx‘ for key ‘xxx‘

热门文章

  1. DNN使用非80端口和总是跳转到http://localhost问题的解决
  2. MySQL 迁移到半同步模式
  3. 最近新学的小东西和单词
  4. C链表反转(时间复杂度O(n))
  5. C语言中return和exit的区别
  6. sql优化技巧_使用这些查询优化技巧成为SQL向导
  7. 如何评价强gis与弱gis_什么是gis的简化解释
  8. C#EF中,使用类似于SQL中的% 模糊查询
  9. React学习笔记(持续更新)
  10. java分页数据导出excel