linux 下常用的创建多线程函数pthread_create(pthread_t * thread , pthread_attr_t * attr , void *(*start_routine)(void*) , void *args);

其中第一个参数用来保存线程信息,第二个参数指新线程的运行属性,可以设置为NULL,第三个参数为自定义的线程函数,第四个参数就是线程函数需要用到的参数,一般如果要传递多个参数,可以设置为结构体(struct)类型,这里我们使用int类型的变量。

下面我着重讨论一个用for结构来创建多个线程时参数传递的问题:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>#define th_pop 20 pthread_mutex_t mutex;pthread_t a_thread[th_pop];void * thread_func(void *args)
{pthread_mutex_lock(&mutex);int t_id = *(int*)args;printf("the id of this thread is %d\n",t_id);pthread_mutex_unlock(&mutex);    return (void*)NULL;
}void init()
{pthread_mutex_init(&mutex, NULL);int i;for( i=0; i<th_pop; i++){pthread_create(&a_thread[i] , NULL , thread_func , &i);}//wait the end of the threads;for( i=0; i<th_pop; i++){int res = pthread_join(a_thread[i] , NULL);if(res != 0)printf("the thread id: %d ends fail \n",i);}pthread_mutex_destroy(&mutex);}int main()
{init();return 0;
}

运行结果:

huangcheng@ubuntu:~$ ./a.out
the id of this thread is 2
the id of this thread is 8
the id of this thread is 9
the id of this thread is 9
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20
the id of this thread is 20

看到这个结果有没有感觉到有什么不对呢?可能你会感觉到很纳闷,怎么出现了那么多的id=0的结果呢?其实这个认真分析一下并不难理解:

首先pthread_create函数传递的是一个指针型的参数,即传递的是一个地址而已,这样在执行for结构时:

for(int i=0; i<th_pop; i++)
{pthread_create(&a_thread[i] , NULL , thread_func , &i);
}

该for循环快速执行完成,并且将i置为20,故而传递的地址指向的内容为20,同时其它的线程还没来得及执行: int t_id = *(int*)args;

这样就使得多个线程都指向同一个地址,内容为20,解决该问题的一个办法为中for结构中加入sleep(1),这样当sleep时间大于线程函数执行时间,就可以得到一个正确的结果,不过这种办法剥掉了并发性,并不可取,下面我们采用另一种方法。

我们只修改init()函数

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>#define th_pop 20 //pthread_mutex_t mutex;pthread_t a_thread[th_pop];void * thread_func(void *args)
{pthread_mutex_lock(&mutex);int t_id = *(int*)args;printf("the id of this thread is %d\n",t_id);pthread_mutex_unlock(&mutex);    return (void*)NULL;
}void init()
{pthread_mutex_init(&mutex, NULL);int thread_id[th_pop];int i;for( i=0; i<th_pop; i++)thread_id[i] = i;for( i=0; i<th_pop; i++){int *t = thread_id +i;pthread_create(&a_thread[i] , NULL , thread_func , (void*)t);}//wait the end of the threads;for( i=0; i<th_pop; i++){int res = pthread_join(a_thread[i] , NULL);if(res != 0)printf("the thread id: %d ends fail \n",i);}pthread_mutex_destroy(&mutex);}int main()
{init();return 0;
}

运行结果:

huangcheng@ubuntu:~$ ./a.out
the id of this thread is 3
the id of this thread is 2
the id of this thread is 1
the id of this thread is 4
the id of this thread is 5
the id of this thread is 6
the id of this thread is 7
the id of this thread is 8
the id of this thread is 9
the id of this thread is 10
the id of this thread is 11
the id of this thread is 12
the id of this thread is 13
the id of this thread is 14
the id of this thread is 15
the id of this thread is 16
the id of this thread is 17
the id of this thread is 18
the id of this thread is 19
the id of this thread is 0

从这个例子中我们应该明白,要避免直接在传递的参数中传递发生改变的量,否则会导致结果不可测。

解决这类问题的办法:

(1)复制一份到堆里面。
(2)加锁。(一般做法)
(3)用结构体数组。(推荐这个)
(4)sleep。(不推荐)

转载于:https://www.cnblogs.com/wangfengju/p/6172684.html

UNIX环境高级编程——pthread_create的问题相关推荐

  1. 【UNIX环境高级编程】线程同步

    当多个线程共享相同的内存时,需要确保每个线程看到一致的数据视图.如果每个线程使用的变量都是其他线程不会读取和修改的,那么就不存在一致性问题.同样,如果变量是只读的也不会有一致性问题.但是,当一个线程可 ...

  2. 《Unix环境高级编程》学习笔记:从点到面

    以前在课堂上学习过<Unix初级教程(第四版)>,对于Unix有了一点了解.由于以后使用的需要,要对它进行比较深入的学习,为此需要阅读不少的书籍,这本<Unix环境高级编程>便 ...

  3. Unix环境高级编程 笔记

    Unix环境高级编程(第二版)学习笔记 这是一次较长时间的整理,然而跳跃了一些章节和很多知识点,仍然是很不完善很不全面的. 前言 操作系统某些问题 严格意义上,可将操作系统定义为一种软件,它控制计算机 ...

  4. UNIX环境高级编程-第三版

    Unix环境高级编程-第三版 之前学习了<Linux系统编程>对于常见的概念和函数都有了基础的认知,这里准备通过这本书,深入学习系统API相关内容.笔记内容会有所倾向,不会严格反应书本内容 ...

  5. 5w字总结 Unix系统编程学习笔记(面试向)(Unix环境高级编程/Unix环境程序设计)

    文章目录 一.计算 C语言的数据表示与处理 计算 C语言的基本运算操作 内存表和符号表 类型转换 函数类型的分析 指令 复合指令 句法 函数 函数激活(Activation Record) 函数激活定 ...

  6. 《UNIX环境高级编程(第3版)》——1.7 出错处理

    本节书摘来自异步社区<UNIX环境高级编程(第3版)>一书中的第1章,第1.7节,作者:[美]W. Richard Stevens , Stephen A.Rago著,更多章节内容可以访问 ...

  7. unix环境高级编程 pdf_UNIX系统编程宝典,每一本都值得程序员珍藏

    这几本UNIX系统编程宝典,重印无数次,几代程序员都视如珍宝的几本书,小编在出版圈里快十年了,见证了这本书图灵版.异步社区版的出版.营销,对这套书倾注了一定的感情.今天继续分享给你们,好书总会有人还不 ...

  8. 开发日记-20190827 关键词 读书笔记《Unix环境高级编程(第二版)》DAY 3

    Referred Blogs 文件描述符标志,文件状态标志 Linux中文件描述符fd和文件指针flip的理解 Linux编程–文件描述符fd 文件共享 Unix支持在不同进程间共享文件. 内核使用了 ...

  9. 开发日记-20190822 关键词 读书笔记《Unix环境高级编程(第二版)》《掌控习惯》DAY 2

    Preface 话说,昨天开始尝试着去改变自己,从基础的习惯开始,11:30准时睡觉,平时差不多12:30才睡觉.按理说,比平时早了一个小时睡觉吧,然后我就把闹钟提前了45分钟,想着还能比平常多睡15 ...

最新文章

  1. 【C语言】关于结构体最后的长度为0或1数组的思考
  2. 检查mysql当前状态
  3. Python学习--最完整的基础知识大全
  4. 如何写好一份简历-校招篇
  5. 获取控件坐标位置一直是0
  6. 三相滤波器怎么接线_单相电机和三相电机怎么接线?为什么三相电机有3或6个接线柱?...
  7. 3dvary灯光材质为什么不亮_关机后电脑灯光闪瞎狗眼?在这里关闭它
  8. android自动路由,GitHub - greatzi/RouterKit: 又一个路由库;Android平台对页面、服务的路由框架。自动化且易用。...
  9. PostgreSQL在何处处理 sql查询之五十四
  10. 原来 Kylin 的增量构建,大有学问! | 原力计划
  11. wpf制作的画图软件
  12. 制作谷歌浏览器 Google Chrome 免安装绿色版!
  13. 自我成长和学习的32个网站,每天逛一逛都有不同的收获
  14. [转载]前端代码规范 及 最佳实践
  15. 英国内政部启动遣返程序 数百非法入境者或遭驱逐
  16. 基于树莓派的遥控小车
  17. 行人检测方法代码汇总
  18. (Vulnhub练习)-- fristileaks渗透实战
  19. PHP连接MySql/SQLServer数据库
  20. 当超跑「遇上」激光雷达,路特斯ELETRE背后还有哪些黑科技

热门文章

  1. 系统如何启动数据库服务器,怎么启动sql数据库服务器
  2. x86_64 arm制linux-gcc,arm-linux-gcc 制作
  3. stm32 SysTick
  4. vue if判断_vue循环判断
  5. string拼接_String拼接操作-的优化
  6. java分隔符算法_《Java数据结构和算法》栈 分隔符分配
  7. 和preload_通过LD_PRELOAD绕过disable_functions
  8. c语言 乘除法优先级,运算符运算符优先级 - C语言教程
  9. java使用linux常用命令_linux常用Java程序员使用命令(一)
  10. IOS UISwitch 组件的使用