1.线程创建函数:
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);
我们知道第一个参数线程ID是传出参数,以便调用它的线程能获取其创建线程的ID,根据线程ID所相应的处理,最后一个参数是传入参数,创建的线程可以获取它做相应操作。
1.我们是否能在创建的线程使用线程ID变量:thread?
当然不能,使用它存在一定的风险,调用它的线程把创建的线程的ID存放在thread中,不过由于thread是一个传出参数,如果新线程在创建线程返回之前就运行了,那么新线程看到thread的值是未初始化的内容,这个内容并不是正确的 线程ID的内容。一般在创建线程中使用pthread_self(),获取当前创建线程的ID。
2 传入参数需要注意的地方,从以下程序来分析:
代码一:
#include <stdio.h>
#include <pthread.h>
void* start_thread(void *param)
{
char *str = (char *)param;
printf("s:%s\n",__func__, str);
return NULL;
}
pthread_t create_test_thread(char * buf)
{
pthread_t id =0;
pthread_create(&id, NULL, start_thread,buf);
return id;
}
int main(void)
{
void *ret = NULL;
char buf[] ="helloword";
pthread_t id = create_test_thread(buf);
pthread_join(id,&ret);
return 0;
}
代码二:
#include <stdio.h>
#include <pthread.h>
void* start_thread(void *param)
{
char *str = (char *)param;
printf("s:%s\n",__func__, str);
return NULL;
}
pthread_t create_test_thread()
{
pthread_t id =0;
char buf[] ="hello world";
pthread_create(&id, NULL, start_thread,buf);
return id;
}
int main(void)
{
void *ret = NULL;
pthread_t id = create_test_thread();
pthread_join(id,&ret);
return 0;
}
代码三:
#include <stdio.h>
#include <pthread.h>
void* start_thread(void *param)
{
char *str = (char *)param;
printf("s:%s\n",__func__, str);
return NULL;
}
pthread_t create_test_thread(char * buf)
{
pthread_t id =0;
pthread_create(&id, NULL, start_thread,buf);
return id;
}
int main(void)
{
void *ret = NULL;
char buf[] ="helloword";
pthread_t id = create_test_thread(buf);
return 0;
}
我们用gcc -o mythread mythread.c -lpthread,并运行./mythread,我们只能从代码一中获取正确的结果,为什么呢?
代码二中:buf的作用域只限于函数create_test_thread()中,函数执行完毕,buf所指向的空间也就释放了,如果主函数执行完毕,创建线程还没启动,那么创建线程使用的buf就是一块不可靠内存,可能产生无法预料的错误。
对于代码三:同样原理,可能创建的线程还没执行,主线程已经运行完毕,那么整个进程已经结束了,当然就得不到想要的结果。
所以我们要在创建的线程,使用主线程传过来参数,需要确保创建线程能够启动,同时获取变量内存空间还没释放。
分享到:
相关推荐
LINUX下多线程编程入门提供,通过大量的例子讲授linux下如何进行多线程编程,和需要注意的地方细节
一个进程池的服务器程序 ... 流程大概如下: 1,父进程listen,创建pipe(下面所有父子进程之间的通信都用该pipe) 2,父进程预fork n个子进程 3,各个子进程accept(listenfd),即所有子进程竞争accept请求。...
-实时调度算法EDF和RMS store_scheduler: 实现了存贮管理--动态不等长存储资源分配算法 HashFile: 实现了文件系统--Hash结构文件 device: 实现了设备管理--Linux设备驱动程序安装(注意头文件的位置随...
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概...
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概...
请注意,现在此文件包含linux要求。 conda会将某些系统库解释为软件包,并且需要将它们分开安装。有关更多详细信息,请参见文件中的注释。安装uwsgi。大多数Python Web应用程序都希望以某种格式WSGI发出HTTP请求。这...
需要注意的是,如果你要用一个IP地址对应多个不同的FTP服务器,则只能用使用不同的端口号的方法来实现,而不支持“主机头名”的做法。 对于已建立好的FTP服务器,在浏览器中访问将使用如“ftp://192.168.0.1”或是...
而在之后的实际使用时,发现oSIP也需要增加OSIP_MT宏,否则OSIP_MT调用oSIP的线程库时会出错,所以我们需要重新编译oSIP了:),因为eXosip是基于oSIP的(同上方式创建静态和...
1、首先检查是不是连接weblogic服务过大部分被拒绝,需要监控weblogic的连接等待情况,此时需要增加acceptBacklog,每次增加25%来提高看是否解决,同时还需要增加连接池和调整执行线程数,(连接池数*Statement ...
您可以将运行库看作一个在执行时管理代码的代理,它提供内存管理、线程管理和远程处理等核心服务,并且还强制实施严格的类型安全以及可提高安全性和可靠性的其他形式的代码准确性。事实上,代码管理的概念是运行库的...
以前编译好的模块(.ec)甚至不需要重新编译即可直接支持静态编译。 支持库开发框架调整是扩展性调整,比较好的做到了向前向后兼容。即,新版支持库可被旧版易语言或易程序使用,旧版支持库也可被新版易语言或易程序...
Linux C++ Python C# Node.Js 一文让你彻底理解 Java HashMap 和 ConcurrentHashMap 2018-07-25 分类:JAVA开发、编程开发、首页精华0人评论 来源:crossoverjie.top 分享到:更多0 前言 Map 这样的 Key ...
CruiseYoung提供的带有详细书签的电子书籍目录 ... 深入理解Android:卷I(51CTO网站“2011年度最受读者喜爱的原创IT技术图书”) 基本信息 ... 如有一些需要特别说明的地方,则会用下面的格式表示: ...
(但是请注意:两个不同但结构上等效的委托类型的实例可能会比较为相等),准确地说,两个具有相同参数列表、签名和返回类型的不同的委托类型被认为是不同的委托类型。委托实例所封装的方法集合称为调用列表。 5, ...
它们提供了足够的可编程特性(变量、流程控制和过程),使你可以将现有程序组装成符合自己需要的复杂的脚本程序。Shell程序非常适用于一些日常任务的自动化处理工作。 Tcl解释器可以很容易地添加到你的应用程序中,...
简单地讲,部署就是安装,就是把软件放置到相应的地方,并且进行相应的配置(一般 称作部署描述),让软件能够正常运行起来。 4.2:Java是一种软件部署环境 ava本身是一个开发的平台,开发后的Java程序也是运行在Java平台上...