在做项目的时候发现,在一个循环创建线程的程序中,创建线程时传入循环改变的变量。但是发现直接传入循环变量没有改变。后来发现是线程执行时会有cpu调度的问题,而此时循环已经结束。
在网上发现下面一片博客写的正是这个问题。记录如下:
linux 下常用的创建多线程函数pthread_create(pthread_t * thread , pthread_attr_t * attr , void *(*start_routine)(void*) , void *args);其中第一个参数用来保存线程信息,第二个参数指新线程的运行属性,可以设置为NULL,第三个参数为自定义的线程函数,第四个参数就是线程函数需要用到的参数,一般如果要传递多个参数,可以设置为结构体(struct)类型,这里我们使用int类型的变量。 下面我着重讨论一个用for结构来创建多个线程时参数传递的问题
先看下面的例子,后面附有结果,先不要看,猜测一下会有什么样的输出:
#include<iostream>
#include<pthread.h>
#include<semaphore.h>
using namespace std;
#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;
cout<<"the id of this thread is "<<t_id<<endl;
pthread_mutex_unlock(&mutex);
return (void*)NULL;
}
void init()
{
pthread_mutex_init(&mutex, NULL);
for(int i=0; i<th_pop; i++)
{
pthread_create(&a_thread[i] , NULL , thread_func , &i);
}
//wait the end of the threads;
for(int i=0; i<th_pop; i++)
{
int res = pthread_join(a_thread[i] , NULL);
if(res != 0)
cout<<"the thread id: "<< i<<" ends fail"<<endl;
}
pthread_mutex_destroy(&mutex);
}
int main()
{
init();
return 0;
}
编译运行
g++ -fpermissive args.cc -o args.o -pthread
./args.o
下面是输出结果,由于线程执行的不确定性,可能你执行的时候得到的结果并非如此,这只是一个代表而已
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=20的结果呢?其实这个认真分析一下并不难理解:
首先pthread_create函数传递的是一个指针型的参数,即传递的是一个地址而已,这样在执行for结构时
for(int i=0; i<th_pop; i++)
{
pthread_create(&a_thread[i] , NULL , thread_func , &i);
}
该块快速执行完成,并且将i置为20,故而传递的地址指向的内容为20,同时其它的线程还没来得及执行 int t_id = *(int*)args;,这样就使得多个线程都指向同一个地址,内容为20,解决该问题的一个办法为中for结构中加入sleep(1),这样当sleep时间大于线程函数执行时间,就可以得到一个正确的结果,不过这种办法剥掉了并发性,并不可取,下面我们采用另一种方法。
我们只修改init()函数
void init()
{
pthread_mutex_init(&mutex, NULL);
int thread_id[th_pop]; for(int i=0; i<th_pop; i++) thread_id[i] = i;
for(int 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(int i=0; i<th_pop; i++)
{
int res = pthread_join(a_thread[i] , NULL);
if(res != 0)
cout<<"the thread id: "<< i<<" ends fail"<<endl;
}
pthread_mutex_destroy(&mutex);
}
下面输出结果
the id of this thread is 0
the id of this thread is 4
the id of this thread is 2
the id of this thread is 5
the id of this thread is 1
the id of this thread is 3
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
从这个例子中我们应该明白,要避免直接在传递的参数中传递发生改变的量,否则会导致结果不可测
分享到:
相关推荐
编译时报 Looking for pthread_create - not found 的解决办法 linux gcc 编译时报Looking for pthread_create - not found 其解决办法是...
向线程函数传递参数的程序示例; 一个资源包,执行 tar zxvf example.tar.gz 解压资源; 复制readme.txt中的编译语句,编译得到可执行程序threadtest; ./threadtest 执行皆可看到效果。
QT中多线程实例,使用C的pthread_create,传递参数,简单易懂,用工程和可执行程序及源代码,仅供参考
问题原因: pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。 问题解决: 在编译...
pthread_testcancel pthread_kill pthread_cancel 的使用例子
以下是对pthread_cond_wait的用法进行了详细的分析介绍,需要的朋友可以过来参考下
pthread_create是UNIX环境创建线程函数 头文件 #include<pthread> 函数声明 int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict ...
为什么在pthread_cond_wait()前要加一个while循环来判断条件是否为假呢?.zip
信号pthread_cond_wait信号pthread_cond_wait信号pthread_cond_wait信号pthread_cond_wait信号pthread_cond_wait
pthread资源包,pthread源码和已经编译好的VS2019_x64版本 #include <pthread.h> ...pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_create(&newThread, &attr, Function_t, NULL);
2.2多线程介绍如果不能从根本上更新当前CPU的架构(在很长一段时间内还不太可能),那么继续提高CPU性能的方法就是超线程CPU模式 2.2.1多线程出现的原因
线程编程——使用pthread_join。 打包文件包含两个文件:c文件源代码、Makefile文件,运行环境在Ubuntu14.04下,使用自带的gcc编译器,同学们只需将文件夹复制到某一目录下之后在终端执行:1.“make”生成“test”可...
线程中处理信号pthread_sigmask 的使用
visual studio多线程支持库,无法解析的外部符号 __imp__pthread_create,该符号在函数 _main 中被引用
Linux进程控制——线程创建 实现代码 #include #include #include void* func(void *arg) { printf(Child thread!\n); printf(Thread ID is %ld\n, (unsigned long... if(pthread_create(&threadId, NULL,func, NULL)
一篇博客内容 pthread_cond_wait详解
pthread_create是UNIX环境创建线程函数 具体格式: #include<pthread> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void*(*start_rtn)(void*),void *restrict arg);...
主要介绍pthread_cread() 的介绍,便于自己学习和回顾。 如有错误欢迎指出。