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
  • 或被取消,终止自己并完成所有资源清理工作;

线程状态转换如下图。

说明

  • 线程开始处于就绪状态;
  • 当线程运行时,它调用特定的起始函数;
  • 它可能被其他线程抢占,或者因等待外来事情而阻塞自己;
  • 最终线程完成工作,或者从起始函数返回,或者调用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多线程—线程基本概念的更多相关文章

  1. posix多线程--线程取消

    1.三种取消状态Off                   禁用取消Deferred           推迟取消:在下一个取消点执行取消Asynchronous   异步取消:可以随时执行取消 in ...

  2. posix多线程--线程私有数据

    1.当多个线程共享一个变量时,将该变量定义为静态或外部变量,使用互斥量确保共享变量的安全访问.如果每个线程都需要一个私有变量值,则该值成为线程的私有数据.程序创建一个键,每个线程独立地设定或得到自己的 ...

  3. POSIX多线程

    全文共分四部分: POSIX多线程—概述    POSIX多线程—异步编程举例    POSIX多线程—线程基本概念    POSIX多线程—互斥量概述 POSIX多线程—概述 Content 1. ...

  4. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

  5. Java多线程1:进程与线程的概念、区别和联系

    一.进程的的概念 引用线程之前进程的概念: 进程是表示资源分配的基本单位,也是调度运行的基本单位.例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括内存空间.磁盘空间.I/O设备等.然 ...

  6. Java高并发和多线程系列 - 1. 线程基本概念

    1. 什么是线程? 线程和进程的区别 在了解线程的概念前,我们应该先知道什么是进程? 进程是操作系统的基本概念之一, 它是正在执行的程序实例. * 下面的一些进程的基本概念你可以了解下 ------- ...

  7. posix多线程--三种基本线程编程模型

    本文介绍了三种构建线程解决方案的方式. 一.流水线:每个线程执行同一种操作,并把操作结果传递给下一步骤的线程. 代码示例如下:终端输入一个int值,每个线程将该值加1,并将结果传给下一个线程. #in ...

  8. java多线程回顾1:线程的概念与创建

    1.进程与线程的概念 现在几乎所有操作系统都支持多任务,通常一个任务就是一个程序,一个运行中的程序就是一个进程.当一个程序行时,其内部也可能在执行多个任务,进程内每一个任务的执行流,就是一个线程. 所 ...

  9. 多线程的基本概念和Delphi线程对象Tthread介绍

    多线程的基本概念和Delphi线程对象Tthread介绍 作者:xiaoru    WIN 98/NT/2000/XP是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU运行 ...

随机推荐

  1. 今日工作总结:jquery轮转效果的集成与前台页面banner的设计思路总结

    今日做了两个项目中的两个问题,现在特来总结一下,以便分享给更多的朋友们. 1.jquery轮转效果的集成 涉及到jquery的不同版本问题,解决办法是在后缀用jQuery代替$.项目地址在:121.4 ...

  2. resty-limit-multiple-strategy.lua

    --[[ 执行过载限流策略 --]] -- 当执行限流时,Nginx 返回的状态码 err_code = local limit_config = { user_limit = {rate = , b ...

  3. python发送信息到邮箱

    import smtplib from email.mime.text import MIMEText 设置服务器所需信息 163邮箱服务器地址 mail_host = 'smtp.163.com' ...

  4. C++11并发编程:原子操作atomic

    一:概述 项目中经常用遇到多线程操作共享数据问题,常用的处理方式是对共享数据进行加锁,如果多线程操作共享变量也同样采用这种方式. 为什么要对共享变量加锁或使用原子操作?如两个线程操作同一变量过程中,一 ...

  5. pL/SQL 创建DBLIKN

    某些时候,需要关联不同的数据库进行数据查询.操作等. 在Oracle中,关联不同的数据库进行表关联,就要用到了数据库连接(DB link). 创建DB link有两种方法:通过SQL语句创建,通过可视 ...

  6. 使用新浪API生成短连接

    公司最近需要进行短信推广,需要发送大批量带有连接地址的短信给用户,并且需要统计短信的点击量.因为需要考虑短信成本问题,需要将长连接地址生成比较短的连接.因为公司本身没有短的一级域名,所以考虑到使用第三 ...

  7. 数据库mysql中编码自动生成

    call PrGetRuleCodeNoDate('Table_Name'); call PrGetRuleCode('Table_Name');

  8. java.util.regex.Pattern正则表达式写验证器示例

    import java.util.regex.Pattern; /** * 校验器:利用正则表达式校验邮箱.手机号等 * */ public class Validator { /** * 正则表达式 ...

  9. 自动化运维与Saltstack

    一.自动化运维介绍 1.自动化运维产生背景   传统的IT运维是将数据中心中的网络设备.服务器.数据库.中间件.存储.虚拟化.硬件等资源进行统一监控,当资源出现告警时,运维人员通过工具或者基于经验进行 ...

  10. 【Android】5.0 第一个工程学习——应用名称和图标修改、增加Buton控件、Toast信息提示

    1.0 搞了很多天,eclipse只能开发Android6.0以前的版本,可能是因为谷歌不再针对eclipse更新了,在虚拟机Android6.0以上版本都无法构建,所以转到Android Studi ...