POSIX多线程—线程基本概念
http://blog.csdn.net/livelylittlefish/article/details/7957007
作者:阿波
链接:http://blog.csdn.net/livelylittlefish/article/details/7957007
(整半年没有更新,发几篇以前的读书笔记。)
content
1. 线程建立与使用
- 创建线程
- 初始线程
- 线程分离
2. 线程生命周期
- 就绪态
- 被阻塞
- 线程终止
- 线程回收
1. 线程建立与使用
创建线程
- 通过pthread_create()函数创建线程;
- 向该函数传递线程函数地址和线程函数参数;
- 线程函数只有一个void*参数;
- 该函数返回pthread_t类型的线程ID;
- 一般调用该函数创建线程,然后调用pthread_join()函数等待线程结束;
- 在当前线程从函数pthread_create()中返回以及新线程被调度执行之间不存在同步关系;
- 新线程可能在当前线程从pthread_create()返回值前就运行了;
- 或在当前线程从pthread_create()返回之前,新线程就可能已经运行完毕了;
pthread_join()
- 阻塞其调用者直到指定线程终止,然后可以选择地保存线程的返回值;
- 当pthread_join()调用返回时,被连接线程就已经被分离(detached),再也不能连接该线程了;
- 如果连接(joining)线程不关心返回值,或者它知道被连接(joined)的线程根本不返回任何值,则可向pthread_join()的&retval参数传递NULL,此时,被连接线程的返回值将被忽略;
如何使用可参考pthread_create()、pthread_join()手册;
初始线程
- C程序运行时,首先运行main()函数,main()函数所在线程称为初始线程或主线程;
- 初始线程可调用pthread_self()获得其ID,也可调用pthread_exit()来终止自己;
- 从main()返回将导致进程终止,也将使进程内所用线程终止;
- 在main()中调用pthread_exit(),这样进程就必须等待所有线程结束后才能终止;
- 若初始线程将其ID保存在一个其他线程可以访问的空间,则其他线程就可以等待初始线程的终止或者分离初始线程;
线程分离
- 分离一个正在运行的线程不会对线程带来任何影响,仅仅是通知系统当该线程结束时,其所属资源可以被回收;
- 分离线程意味着通知系统不再需要此线程,允许系统将分配给它的资源回收;
- 一个没有被分离的线程终止时会保留其虚拟内存,包括堆栈和其他系统资源。
2. 线程生命周期
在任意时刻,线程处于下表的四个基本状态之一。
状态 |
说明 |
就绪ready |
线程能够运行,但在等待可用的处理器;
|
运行running |
线程正在运行;在多处理器系统中,可能有多个线程处于运行状态; |
阻塞blocked |
线程由于等待处理器外的其他条件无法运行,如条件变量的改变、加锁互斥量或IO操作结束; |
终止terminated |
不是被分离,也不是被连接,一旦线程被分离或者连接,它就可以被回收;
|
线程状态转换如下图。
说明
- 线程开始处于就绪状态;
- 当线程运行时,它调用特定的起始函数;
- 它可能被其他线程抢占,或者因等待外来事情而阻塞自己;
- 最终线程完成工作,或者从起始函数返回,或者调用pthread_exit函数,即进入终止状态;
- 如果线程已被分离,则它立刻被回收重用;否则,线程停留在终止状态直到被分离或被连接;
就绪态
- 线程刚被创建时;
- 线程被解除阻塞再次可以运行时;
- 运行线程被抢占时,如时间片到;
被阻塞
- 试图加锁一个已经被锁住的互斥量;
- 等待某个条件变量;
- 调用singwait等待信号;
- 执行无法立即完成的IO操作;
- 内存页错误之类的系统操作;
初始线程(main()函数所在线程)与普通线程区别
- 初始线程的启动函数main()是从程序外部调用的;如crt0.o文件复制初始化进程并调用main()函数;而普通线程的启动函数及其运行参数均由pthread_create()函数创建线程时传入,且由CPU调度的;
- main()函数的参数是argc和argv;普通线程的参数是void*,且由pthread_create()函数传入;
- 若普通线程从启动函数中返回,则线程终止,而其他线程依然可以运行;但初始线程从main()返回时,进程终止,进程内所有线程也被终止;
- 若希望在初始线程终止时,进程中的其他线程继续执行,则需要在初始线程调中调用pthread_exit()而非从main()返回;
- 大多数系统,初始线程运行在默认进程堆栈上,该堆栈可以增长到足够尺寸;而某些实现中,普通线程的堆栈空间是受限的;
- 如果线程堆栈溢出,则程序会出现段错误;
线程睡眠原因
- 被阻塞,需要的某个资源不可用;
- 被抢占,即系统将处理器分配给其他线程;
pthread_join()的详细解释
- 用来等待一个线程的结束;
- 是一个线程阻塞函数,调用它的函数将一直等待到被等待的线程结束为止;
- 如,主线程调用pthread_join()等待它创建的线程运行结束,即主线程调用该函数后会被阻塞;
- 当函数返回时,被等待的线程的资源被回收;
- 若此时新线程没有运行,则它将在主线程被阻塞后从就绪态进入运行态;当新线程运行完毕并返回时,主线程才会被解除阻塞,返回就绪态;当处理器可用时,主线程或立即执行或等到创建的线程终止后重新运行直到结束;
线程终止
- 一般地,线程从启动函数返回来终止自己;
- 当调用pthread_exit()退出线程或者调用pthread_cancel()取消线程时,线程在调用每个清理过程后也进入终止状态;
- 清理过程又线程通过pthread_cleanup_push()注册,且尚未通过pthread_cleanup_poo()删除;
Linux系统僵尸线程
- 如果线程已经被分离,则会被回收;否则,线程处于终止状态,仍然可以被其他线程调用pthread_join()连接;
- 这种线程被称为僵尸线程,像Unix系统中的进程已经结束但还没有被一个wait/waitpid调用回收一样,即使已经死了但还存在;
- 僵尸线程可能会保留其运行时的大部分甚至所有资源,因此不应该让线程长时间处于这种状态;当创建不需要连接的线程时,应该使用detachstate属性建立线程使其自动分离;
线程回收
- 如果使用detachstate属性(即设置属性为PTHREAD_CREATE_DETACH)建立线程,或者调用pthread_detach()分离线程,则当线程结束时将被立刻回收;
- 如果终止线程没有被分离,则它将一直处于终止状态直到被分离(通过pthread_detach)或者被连接(通过pthread_join);
- 线程一旦被分离,就不能再访问它;
- 回收将释放所有在线程终止时未释放的系统和进程资源,包括
- 保存线程返回值的内存空间、堆栈;
- 保存寄存器状态的内存空间;
- 实际上线程终止时上述资源就不能被访问了;
- 一旦线程被回收,线程ID就无效了,不能再连接、取消或者执行其他任何操作;
- 终止线程ID可能被分给新线程;
NPTL (Native POSIX Threads Library)
This is the modern Pthreads implementation. By comparison with LinuxThreads, NPTL provides closer conformance to therequirements of the POSIX.1 specification and better performance when creating largenumbers of threads. NPTL is available since glibc 2.3.2, and requires features that are present in theLinux 2.6 kernel.
Thread-safe functions
A thread-safe function is one that can be safely (i.e., it will deliver the same results regardless of whetherit is) called from multiplethreads at the same time.
Reference
# man pthreads
# man pthread_create
# man pthread_join
# man pthread_exit
# man pthread_cancel
POSIX多线程—线程基本概念的更多相关文章
- posix多线程--线程取消
1.三种取消状态Off 禁用取消Deferred 推迟取消:在下一个取消点执行取消Asynchronous 异步取消:可以随时执行取消 in ...
- posix多线程--线程私有数据
1.当多个线程共享一个变量时,将该变量定义为静态或外部变量,使用互斥量确保共享变量的安全访问.如果每个线程都需要一个私有变量值,则该值成为线程的私有数据.程序创建一个键,每个线程独立地设定或得到自己的 ...
- POSIX多线程
全文共分四部分: POSIX多线程—概述 POSIX多线程—异步编程举例 POSIX多线程—线程基本概念 POSIX多线程—互斥量概述 POSIX多线程—概述 Content 1. ...
- -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中
本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait( ...
- Java多线程1:进程与线程的概念、区别和联系
一.进程的的概念 引用线程之前进程的概念: 进程是表示资源分配的基本单位,也是调度运行的基本单位.例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括内存空间.磁盘空间.I/O设备等.然 ...
- Java高并发和多线程系列 - 1. 线程基本概念
1. 什么是线程? 线程和进程的区别 在了解线程的概念前,我们应该先知道什么是进程? 进程是操作系统的基本概念之一, 它是正在执行的程序实例. * 下面的一些进程的基本概念你可以了解下 ------- ...
- posix多线程--三种基本线程编程模型
本文介绍了三种构建线程解决方案的方式. 一.流水线:每个线程执行同一种操作,并把操作结果传递给下一步骤的线程. 代码示例如下:终端输入一个int值,每个线程将该值加1,并将结果传给下一个线程. #in ...
- java多线程回顾1:线程的概念与创建
1.进程与线程的概念 现在几乎所有操作系统都支持多任务,通常一个任务就是一个程序,一个运行中的程序就是一个进程.当一个程序行时,其内部也可能在执行多个任务,进程内每一个任务的执行流,就是一个线程. 所 ...
- 多线程的基本概念和Delphi线程对象Tthread介绍
多线程的基本概念和Delphi线程对象Tthread介绍 作者:xiaoru WIN 98/NT/2000/XP是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU运行 ...
随机推荐
- js - cannot set property xxx of undefined
for(let i=0;i<=res.data.length;i++){ res.data[i]['class'] = 'biaoqian-red'; } console.log(res.dat ...
- Quartz和TopShelf Windows服务作业调度
上一次写了一遍关于Quartz作业调度的文章 Quartz.NET 作业调度使用 现在使用TopShelf和Quartz实现windows服务作业调度 TopShelf版本4.0 Quartz版本3. ...
- GreenPlum 大数据平台--备份-邮件配置-gpcrondump & gpdbrestore(五)
01,备份 生成备份数据库 [gpadmin@greenplum01 ~]$ gpcrondump -l /gpbackup/back2/gpcorndump.log -x postgres -v [ ...
- 关于重定向printf出错 Error[Pe020]: identifier "FILE" is undefined 解决方案
IAR或者Keil用到重定向printf函数出现的错误解决方案 转发请注明出处,谢谢 原创:李剀 https://www.cnblogs.com/kevin-nancy/articles/105851 ...
- 【python数据分析】利用Anaconda在window上搭建数据分析环境
由于在进行数据分析过程中,需要安装一些第三方库,导致python总会报一些错误,现将通过利用Anaconda搭建数据分析环境,已测可用. 1.到官网上下载python:https://www.pyth ...
- 《X86汇编语言:从实模式到保护模式》读书笔记之引言
有幸结识了<X86汇编语言:从实模式到保护模式>一书.我觉得这本书非常好,语言活泼,通俗易懂,源码丰富,受益匪浅.读罢一遍,意犹未尽.于是打算再读一遍,并把自己的读书所学总结成笔记,一来给 ...
- [Scala] Pattern Matching(模式匹配)
Scala中的match, 比起以往使用的switch-case有著更強大的功能, 1. 傳統方法 def toYesOrNo(choice: Int): String = choice match ...
- js获取文件输入框的真实目录
1.问题 页面有一个input file服务器控件,一个div,div是image标签的容器,当点击input file的值改变,我们往div里追加image标签: 但当通过js的onchange事件 ...
- 远程SQL Server连接不上
运行 cmd -> 输入 netsh winsock reset重启后 应该可以连接sql了
- for循环的几种比较
对一个集合遍历的3种方法:1.for(int i=0;i<list.size();i++) 2.for(int i=0,len=list.size();i<len;i++) 3.for ( ...