Pthreads线程的基本常识
1.Pthreads中线程的接口函数
与线程相关的头文件为pthread.h,编译时要连接的库为pthread。
pthread_t thread;
线程的数据类型为pthread_t。
int pthread_equal(pthread t1,pthread t2);
判断两个线程标识符是不是代表的是同一个线程。线程标识符只有相等和不等的关系,没有大小关系。
int pthread_create(pthread_t * thread,
const pthread_attr_t * attr, void *(*start)(void *),void * arg);
pthread_create函数将创建一个线程,第一个传出参数为系统分配给线程的标识符。第二个参数为线程设置的属性。第三个参数为线程开始运行后执行的启动函数。第四个参数为函数要用到的参数。
pthread_t pthread_self(void);
pthread_self函数将获得当前线程的标识符。返回值即为当前线程的标识符。获得线程标识符的方法有两种:(1)使用pthread_create函数.(2)使用pthread_self函数.
int sched_yield(void);
志愿让出处理器的使用权给其他线程使用。
int pthread_exit(void * value_ptr);
当前线程退出。
int pthread_detach(pthread_t thread);
当线程进入终止状态时,清理线程所占资源后进入回收状态。
int pthread_join(pthread_t thread,void ** value_ptr);
阻塞等待thread线程执行结束,并得到该线程的返回值。注意第二个参数应该为指针的指针。该函数内部会负责调用pthread_detach保证线程的资源得到释放。
2.主线程和普通线程的区别
(1)主线程使用return、exit、或者正常执行到主函数的结尾退出时,所有的线程都将退出。如果主线程需要其他线程执行结束后才退出,可以使用以下方式:1)调用pthread_join,这时调用的主线程将被阻塞,直到join的线程执行结束后,才接着往下执行。2)调用pthread_exit函数,但是pthread_exit函数返回主线程后,系统不能正常得到程序的返回状态。3)使用条件变量等待其他线程执行结束。
(2)主线程的参数传递方式和普通线程不一样,主线程通过main函数中的argc和argv得到各个参数,而普通线程需要将所有的参数封装到一起,传给线程的参数。
(3)一般主线程的栈的大小比普通现成的大很多。主线程使用的是进程的栈,所以会比较大。
(4)主线程的main函数是被外部的某个函数调用的,一般是链接的crt0.o这个文件。ctr0(C running time)是一个启动例程,负责完成进程的初始化工作后,调用main函数。普通线程直接调用start函数。
3.线程的资源回收
线程执行完毕之后应该是放其所占用的资源:包括虚拟内存,堆栈,锁,信号量等信息。一般线程调用了pthread_cancel,pthread_exit或者执行完其start函数中的逻辑或者执行完了return语句,线程的状态将进入终止状态。进入终止状态的线程并没有释放它所占用的资源,一般有以下三种方式:
(1)创建线程的时候在第二个参数中设置detach属性。
(2)使用pthread_detach函数
(3)使用pthread_join函数
线程所占用的资源有些被释放,有些被回收利用。在启动新的线程的时候可以减少一部分开销。
线程的分离(detach)同线程执行其逻辑没有必然联系。还有需要注意的是,一个线程只能被join一次,如果有多个线程都需要等待一个线程,使用信号量实现。
pthread_cancel结束的线程,其返回值只有一种:PTHREAD_CANCELLED
4.线程的返回值
使用线程的返回值最容易出现的错误就是使用了线程内部的栈中数据的地址作为返回值。A线程创建了B线程,B线程可能会在A线程开始执行join之前,已经detach掉了。其栈早已失效,这时如果线程内部返回的是栈中某数据的地址一定出错。
一般线程的返回值可以使用以下三种方式:
(1)使用全局变量
(2)线程内部使用malloc开辟空间,回传给需要的线程。该线程负责释放这段内存
(3)使用传出参数,即调用线程使用malloc在堆上开辟空间,并负责数据的维护
5.代码示例
- #include<stdio.h>
- #include<pthread.h>
- #include "../error.h"
- void * thread_routin(void * arg)
- {
- return arg;
- }
- int main(int argc,char * argv[])
- {
- pthread_t thread;
- void * thread_result;
- int status;
- status = pthread_create(&thread,NULL,thread_routin,NULL);
- if(0 != status)
- err_abort("create thread error.",status);
- status = pthread_join(thread,&thread_result);
- if(0 != status)
- err_abort("join thread error.",status);
- if(NULL != thread_result)
- fprintf(stderr,"%s","Return value error.\n");
- return 0;
- }
- 以上程序是一个简单的参数传入传出的示例程序。
- #include<pthread.h>
- #include<stdio.h>
- #include<stdlib.h>
- int main(int argc,char * argv[])
- {
- pthread_t thread;
- int status;
- status = pthread_join(thread,NULL);
- if(0 != status)
- {
- fprintf(stderr,"%s \"%s\":%d: %s\n","thread join error",__FILE__,__LINE__,strerror(status));
- abort();
- }
- return 0;
- }
以上程序是一个故意出错的程序,在Linux中程序会直接崩溃,提示“段错误”。
- #include<stdio.h>
- #include<pthread.h>
- #include<time.h>
- #include "../error.h"
- void * thread_routin(void *arg)
- {
- sleep(5);
- return arg;
- }
- int main(int argc,char *argv[])
- {
- pthread_t thread ;
- int status;
- int result;
- status = pthread_create(&thread,NULL,thread_routin,NULL);
- if(0 != status)
- err_abort("creating thread error.",status);
- result = 1;
- pthread_exit((void *)&result);
- //return 0;
- }
这是一个测试main线程调用pthread_exit能否返回需要的值的测试程序。该程序表明:在main线程中使用pthread_exit虽然能保证其他线程执行完毕,但是在系统无法得知整个程序的最后执行状态。
- #include<stdio.h>
- #include<pthread.h>
- #include<time.h>
- #include "../error.h"
- void * thread_routin(void *arg)
- {
- //pthread_exit(arg);
- return arg;
- }
- int main(int argc,char *argv[])
- {
- pthread_t thread ;
- void * result;
- int status;
- int set_result = -1;
- status = pthread_create(&thread,NULL,thread_routin,(void *)&set_result);
- if(0 != status)
- err_abort("creating thread error.",status);
- status = pthread_join(thread,&result);
- if(0 != status)
- err_abort("joining thread error.",status);
- printf("exit value is %d\n",*((int *)result));
- pthread_exit((void*)&set_result);
- }
该程序对普通线程和主线程分别调用pthread_exit以测试线程的返回值。主线程的返回值系统无法得到,普通线程的返回值却可以得到。
本文转自hipercomer 51CTO博客,原文链接:http://blog.51cto.com/hipercomer/909941
Pthreads线程的基本常识相关推荐
- posix多线程有感--线程高级编程(线程和fork,exec)
当多线程进程调用fork创建子进程时,Pthreads指定只有那个调用fork的线程在子进程内存在(表示子进程中只有调用线程这个线程).尽管当从fork调用返回时,只有调用线程在子进程中存在,所有其他 ...
- 简单Linux C线程池
大多数的网络服务器,包括Web服务器都具有一个特点,就是单位时间内必须处理数目巨大的连接请求,但是处理时间却是比较短的.在传统的多线程服务器模型中是这样实现的:一旦有个请求到达,就创建一个新的线程,由 ...
- linux线程 ppt,Linux多线程编程多核编程.ppt
<Linux多线程编程多核编程.ppt>由会员分享,可在线阅读,更多相关<Linux多线程编程多核编程.ppt(28页珍藏版)>请在装配图网上搜索. 1.Linux多线程编程, ...
- 【JVM技术专题】较为深入分析线程池基本原理及实现机制「 入门篇」
基本原理 线程池基本常识 线程池(Thread Pool)是一种基于池化思想管理线程的工具.线程频繁的创建.销毁会产生大量的系统内核调用,消耗CPU资源.用线程池来维护多个线程的生命周期,一方面可以避 ...
- Linux学习06——线程控制与同步互斥
概述 学习目标: 理解线程概念和并发特征,分辨线程与进程的区别与联系 掌握多线程应用编程技术,掌握线程间数据传递基本方法 掌握共享变量识别方法,理解多线程访问共享变量可能带来的问题 理解临界资源.临界 ...
- C++ 从双重检查锁定问题 到 内存屏障的一些思考
文章目录 1. 问题描述 2. DCLP 的问题 和 指令执行顺序 2.1 Volatile 关键字 2.2 C++11 的内存模型 3. C++11内存模型 解决DCLP问题 3.1 内存屏障和获得 ...
- 《POSIX多线程程序设计》读书笔记
<POSIX多线程程序设计>读书笔记 一. 概述 1. 一个UNIX进程可以理解为一个线程加上地址空间.文件描述符和其他数据: 2. 多个线程可以共享一个地址空间,而 ...
- linux多线程编写哲学家,Linux系统编程(三) ------ 多线程编程
一.线程的创建和调度 1.线程是程序执行的某一条指令流的映像. 为了进一步减少处理机制的空转时间,支持多处理器及减少上下文切换开销,进程在演化中出现了另一个概念--线程.它是进程内独立的一条运行路线, ...
- 多线程编程指南 part 2
多线程编程指南 Sun Microsystems, Inc. 4150 Network Circle Santa Clara, CA95054 U.S.A. 文件号码819–7051–10 2006 ...
- vlc内部运行机制以及架构分析
VLC架构剖析1. VideoLan简介1.1 videolan组成Videolan有以下两部分组成:VLC:一个最主要的部分,它可以播放各种类型的媒体文件和流 vlc架构剖析 1. VideoLan ...
最新文章
- MySQL数据库初识(基础语句)
- 统计0到n之间1的个数
- minAreaRect函数
- 使用telnet命令验证邮箱
- php删除文见,php如何删除文件夹
- 遗传算法(Genetic Algorithm,GA)实例详解
- 调戏木马病毒的正确姿势-基础篇
- 奈奎斯特稳定判据matlab处理,控制理论-奈奎斯特稳定判据学习笔记-综合电源技术-世纪电源网社区...
- Word 去除页眉横线
- Compose 跨平台的现状
- rasp 系统_Java RASP技术详细介绍及应用「附RASP参考资料」
- wps在线编辑梳理(此处整理了对接过后容易出错的地方)
- Moses的安装、训练和优化
- 一建报名条件是什么?
- excel切片器_不喜欢Excel自带的切片器样式,我一秒设置个性化切片器
- 代码随想录训练营day2
- html的视频字幕制作步骤,视频滚动字幕怎么制作(上)
- Windows驱动_WSK驱动之三WSK编程注意事项
- 平方数列、立方数列求和公式与推导
- js 正则表达式大全
热门文章
- [转载]【深入Java虚拟机】之四:类加载机制
- [转]Handsontable对单元格的操作
- PL\SQL设置中文
- 网络干货,无论是运维还是开发都要知道的网络知识系列之(八)
- Java面试题-Java中的锁
- 回溯---数字键盘组合
- AcWing 166. 数独
- failed to load resource the server responded with a status of 500 (internal server error)
- centos nginx和tomcat集群
- Cannot change version of project facet Dynamic Web Module to 3.0