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。(不推荐)

UNIX环境高级编程——pthread_create的问题的更多相关文章

  1. (九) 一起学 Unix 环境高级编程 (APUE) 之 线程

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  2. (十) 一起学 Unix 环境高级编程 (APUE) 之 线程控制

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  3. UNIX环境高级编程——线程属性

    pthread_attr_t 的缺省属性值 属性 值 结果 scope PTHREAD_SCOPE_PROCESS 新线程与进程中的其他线程发生竞争. detachstate PTHREAD_CREA ...

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

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

  5. (十三) [终篇] 一起学 Unix 环境高级编程 (APUE) 之 网络 IPC:套接字

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  6. multiple definition of `err_sys' 《UNIX环境高级编程》

    本文地址:http://www.cnblogs.com/yhLinux/p/4079930.html 问题描述: [点击此处直接看解决方案] 在练习<UNIX环境高级编程>APUE程序清单 ...

  7. unix环境高级编程基础知识之第二篇(3)

    看了unix环境高级编程第三章,把代码也都自己敲了一遍,另主要讲解了一些IO函数,read/write/fseek/fcntl:这里主要是c函数,比较容易,看多了就熟悉了.对fcntl函数讲解比较到位 ...

  8. (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  9. (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

随机推荐

  1. linux修改root账户的用户名所得的教训

    之前linux服务器的密码被别人改过, 然后叫服务器相关的负责人重置了root账户(服务器负责人在客户所在公司), 重置好之后, 领导叫更改下root 用户名和密码, 于是我二话不说就开始找方法, 找 ...

  2. pm2进阶使用

    启用集群模式 只需要在启动应用时带上i参数 pm2 start app.js -i max max:意味着PM2将自动检测可用的CPU数量和运行多个进程可以在负载均衡模式(但是不推荐使用) 或者使用j ...

  3. django.db.utils.ProgrammingError: 1146 的解决办法

    在models中设置完数据库相关的东西后执行命令 python manage.py makemigrations 此处无错误 再次执行 python manage.py migrate 发生报错 错误 ...

  4. c++类的声明

    就像函数的声明与定义分离一样,我们也可以仅声明类而暂时不定义类: class ClassName;//ClassName类的声明 这种声明有时被称作前向声明 对于一个类来说,我们创建它的对象之前该类必 ...

  5. 判定程序员等级,HashMap就够了

    JDK1.8  HashMap源码分析 用到的符号: ^异运算:两个操作数相同,结果是;两个操作数不同,结果是1. &按位与:两个操作数都是1,结果才是1. 一.HashMap概述 在JDK1 ...

  6. MongoDB实用教程

    ---------------------------------------------------------------------------------------------------- ...

  7. LAB颜色空间各通道的取值范围

    简介 LAB颜色空间在计算机视觉中经常被使用,知道L,A,B三个通道的取值范围有一定的意义. OpenCV获取LAB取值范围 下面是一段实验代码,用于获取LAB的取值范围. 基本思路是,排列组合所有R ...

  8. Rxjava +Retrofit 你需要掌握的几个技巧,Retrofit缓存,RxJava封装,统一对有无网络处理,异常处理, 返回结果问题

    本文出处 :Tamic 文/ http://blog.csdn.net/sk719887916/article/details/52132106 Rxjava +Rterofit 需要掌握的几个技巧 ...

  9. Unity UGUI实现分段式血条

    我们可以看到像英雄联盟等游戏里英雄头顶的血条显示并非是纯色的,而是根据血量的多少而显示一定量的格子,这种方式明显是比较友好.比较美观的,事实上我们的游戏里面也想实现这样的效果,那该怎么办呢?根据血量的 ...

  10. 理解性能的奥秘——应用程序中慢,SSMS中快(4)——收集解决参数嗅探问题的信息

    本文属于<理解性能的奥秘--应用程序中慢,SSMS中快>系列 接上文:理解性能的奥秘--应用程序中慢,SSMS中快(3)--不总是参数嗅探的错 前面已经提到过关于存储过程在SSMS中运行很 ...