http://blog.csdn.net/lanyan822/article/details/7586845

POSIX线程数据类型:

  pthread_t  线程标识符;

  pthread_mutex_t   互斥量;

  pthread_codet_t   条件变量;

  pthread_key_t     线程私有权握访问键

  pthread_attr_t    线程属性对象

  pthread_mutexattr_t  互斥量属性对象

  phtread_condattr_t    条件变量属性对象;

  pthread_once_t    一次性初始化 控制变量 

线程中的基本概念:

  程序中使用线程标识符ID来表示线程。线程ID属于封装的pthread_t类型;

1.创建线程

  Pthread系统中建立线程的主要方式是调用pthread_create. 如果进程的信号通知机制设为:SIGVE_THREAD,  当线程收到一个POSIX信号时也会创建一个线程。系统中可能还存在其他创建线程的方式

    pthread_t pthread_id;

    int status = pthread_create(&pthread_id, NULL,  thread_func,  NULL);

    第三个参数:函数指针;

    第四个参数:函数的参数指针;

  关于thread_func(线程调用函数):   

    线程函数必须是如下形式,即返回类型为:void* , 参数类型为:void* ;   

    typedef void* (*func)(void* );  //不能写成typedef  void*  (*func)(void* i);

    传、取参数的时候特别注意,传的时候要先转为void*,  取参数的的时候要转回原有的类型;(切记、切记)

2. 线程的启动(一般线程函数启动之后就被阻塞了,直到唤醒)

  一旦线程来创建,最终它将开始执行机器指令。 初始指令序列将 带来 在pthread_create调用 中指定的 线程启动函数的执行。

线程启动函数 的运行参数 也是在创建线程时指定的,-----第四个参数;

  在初始线程中, 线程的启动函数(即main函数) 是从程序外部被调用的。 (系统中有文件负责 初始化进程, 然后调用main函数)

初始化线程 与 普通线程 之间存在一些的不同。

  a. main函数的调用参数( argc  and  argv )与普通线程的启动函数不同( void * 参数 )。

   b.如果普通线程从启动函数中返回,则线程终止而其他线程依然可以运行;

    但初始化进程从main函数中返回时,进程终止(进程内所有线程也被 终止)。

    如果希望在初始化线程终止时,进程中的其他线程继续执行,则需要 在初始化线程中调用pthread_exit而不是从main函数返回;

   c.在大多数系统中, 初始线程运行 在默认进程堆栈上; 该堆栈可以增长到足够的大小; 而在某些实现中,普通的堆栈空间是受限的,  如果线程堆栈溢出,则程序会因为段错误或者总线错误而失败;

3. 运行和阻塞

  线程之所以会睡眠是因为 它需要的某个资源不可用(即被阻塞), 或者因为 系统将处理器分配给其他线程(即被抢占)

  线程大多数时间处于其生命周期中的三个状态:  就绪, 运行 和阻塞;

  线程在以下情况被阻塞:

    1.试图加锁一个已经被锁住的互斥量;

    2.等待某个条件变量;

    3.调用Singwait等待尚未发生的信号;

    4.执行无法立即完成的I/O操作

    5.线程还有由于内存页错误之类的系统操作而被阻塞;

    如果新线程此时没有运行, 则新线程将在主线程被阻塞后, 从就绪态 进入运行态。

    当新线程运行完毕并返回时,主线程才会被解除阻塞,返回就绪态。

      主线程 或者立即执行 或者 等到创建的线程 终止 后 重新运行直到结束;

   调用pthread_join()函数 等待它创建的线程运行结束;  

      pthread_join使一个线程等待另一个线程结束。代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。
     所有线程都有一个线程号,也就是Thread ID。其类型为pthread_t。通过调用pthread_self()函数可以获得自身的线程号。
 
    一个线程的结束有两种途径,
      一种是象我们下面的例子一样,函数结束了,调用它的线程也就结束了;
      另一种方式是通过函数pthread_exit来实现。
  另外需要说明的是,一个线程不能被多个线程等待,也就是说对一个线程只能调用一次pthread_join,否则只有一个能正确返回,其他的将返回ESRCH 错误;  

4.终止

  线程通常从启动函数中返回来终止自己;

  当调用 pthread_exit退出线程或者调用pthread_cancel 取消线程时, 线程在调用完每个清理过程中也将进入终止态; 这些清理过程 是由线程通过调用pthread_cleanup_push注册的;而且尚未通过调用 pthread_cleanup_pop删除;

  线程还会有私有“线程特定数据”; 如果线程有非空的私有数据值,则与这些数据相关的 destructor函数将被调用;

  如果线程已经被分离。 则它立刻进入下一个环节--------回收;

  否则,线程处于终止态,它还可以被其他线程调用pthread_join 连接--------僵尸线程;因为即使它们已经死了;但还存在,僵尸线程可能会保存其运行时的大部分资源甚至是所有资源。因此不应该让线程长时间处于这种状态;

  当创建不需连接的线程时,应该使用detachstate属性建立线程 使其自动分离;(还有第二种办法)

  终止后线程至少保留了线程ID(pthread_t数据类型)和 void *返回值;

5.回收

  分离一个正在运行的线程不会对线程带来任何影响,仅仅是通知系统当该线程结束时候,其所属资源可以被回收。

  为了确保终止线程的资源对进程可用,应该在每个线程 结束时分离他们。一个没有被分离的线程终止时会保留其虚拟内存。包括他们的堆栈 和其他系统资源。

  分离线程意味着 通知系统不再 需要此线程,允许系统将分配给它的资源回收;

  如果使用detachstate属性(设为PTHREAD_CREATE_DETACH)建立线程; 或者 调用 pthread_detach分离线程, 则当线程结束时将立刻回收;

   如果终止线程没有被分离,则它将一直处于终止态直到    1、被分离(通过pthread_detach分离) 或者  2、被连接(通过pthread_join)

线程一旦被分离就不能再访问它;

  回收将  释放 (所有线程  终止时未释放的系统 和进程资源,包括保存线程返回值的内存空间,堆栈,保存寄存器状态的内存空间等); 其中一些资源可能已在线程终止时被释放,

  但必须记住:线程终止后上述资源就不该被访问了。    如果一个线程将其堆栈空间指针通过共享数据传给另一个线程,则该线程终止后,此数据就是陈旧数据了;

  一旦 线程被回收,线程ID就无效了; 不能 再连接它、取消它或者执行其他任何操作。

  终止线程ID(可能是系统数据结构地址)可能被分给新的线程;使用该ID调用pthread_cancel 可能会取消一个不同的线程,而不是返回一个ESRCH错误;

  终止线程将释放所有系统资源,但必须自己先释放有该线程占有的程序资源,调用malloc 或者 mmap 分配的内存可以在任何时候,有任何线程释放。

   互斥量、条件变量、和信号灯 可以由任何线程销毁。只要他们被解锁 并没有线程等待;  但是,只有互斥量的主人能够解锁它。 如果线程终止时还有加锁的互斥量。则该互斥量就不能被再次使用(因为不会被解锁)

  pthread_exit()用于线程退出,可以指定返回值,以便其他线程通过pthread_join()函数获取该线程的返回值。
    return是函数返回,只有线程函数return,线程才会退出。

  exit是进程退出,如果在线程函数中调用exit,进程中的所有函数都会退出!

线程的终止

  三种方式:  

    线程从执行函数返回,返回值是线程的退出码

    线程被同一进程的其他线程取消

    调用pthread_exit()函数退出。这里不是调用exit,因为线程调用exit函数,会导致线程所在的进程退出。

linux之线程的更多相关文章

  1. Linux/Unix 线程同步技术之互斥量(1)

    众所周知,互斥量(mutex)是同步线程对共享资源访问的技术,用来防止下面这种情况:线程A试图访问某个共享资源时,线程B正在对其进行修改,从而造成资源状态不一致.与之相关的一个术语临界区(critic ...

  2. Linux获取线程tid线程名

    Linux获取线程tid线程名 1 2 3 4 5 6 //thread name char cThreadName[32] = {0}; prctl(PR_GET_NAME, (unsigned l ...

  3. Linux编程---线程

    首先说一下线程的概念.事实上就是运行在进程的上下文环境中的一个运行流.普通进程仅仅有一条运行流,可是线程提供了多种运行的路径并行的局面. 同一时候,线程还分为核心级线程和用户级线程.主要差别在属于核内 ...

  4. Linux 多线程 - 线程异步与同步机制

    Linux 多线程 - 线程异步与同步机制 I. 同步机制 线程间的同步机制主要包括三个: 互斥锁:以排他的方式,防止共享资源被并发访问:互斥锁为二元变量, 状态为0-开锁.1-上锁;开锁必须由上锁的 ...

  5. Linux 默认线程栈大小 调优

    Linux 线程栈介绍 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区.里面的变量通常是局部变量.函数参数等:和堆相比,栈通常很小. Linux 查询线程栈 1.查看默认的 ...

  6. Linux内核线程创建

    本文旨在简单介绍一下Linux内核线程: 先举个例子: 不插U盘,在Linux命令行中输入:ps -el:然后插上U盘,再次输入:ps -el 会发现多出了下面一行(当然还会有其他的,比如scsi相关 ...

  7. Linux 下线程的理解

    2017-04-03 最近深入研究了下Linux线程的问题,发现自己之前一直有些许误解,特记之…… 关于Linux下的线程,各种介绍Linux的书籍都没有深入去解释的,或许真的如书上所述,Linux本 ...

  8. Linux中线程使用详解

    线程与进程为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?我们首先必须回答这些问题. 使用多线程的理由之一是和进程相比,它是一种非常"节俭&qu ...

  9. Linux中线程的挂起与恢复(进程暂停)

    http://www.linuxidc.com/Linux/2013-09/90156.htm 今天在网上查了一下Linux中对进程的挂起与恢复的实现,相关资料少的可怜,大部分都是粘贴复制.也没有完整 ...

  10. linux系统——线程

    linux系统线程 1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者.传统的Unix也支持线程的概念,但是在一个 ...

随机推荐

  1. CSS3 Test

    CSS3Test 如何判定一个浏览器对css3的支持情况呢 有这么一个站点http://css3test.com 可以测试浏览器对CSS3的支持情况 对应的Github在这里 原理 实际上浏览器对CS ...

  2. @RISK

    Price: AUD $3,295.00   Price: AUD $2,495.00   适用于项目管理的 @RISK 免费试用版下载 » 立即购买 » 价格对比 » 许可选项 (英文) » 教学计 ...

  3. ANDROID SHAPE画圆形背景_ANDROID实现角标布局

    ANDROID SHAPE画圆形背景_ANDROID实现角标布局 <?xml version="1.0" encoding="UTF-8"?> &l ...

  4. rsyslog 传输mysql 日志

    在另外一种环境中,让我们假定你已经在机器上安装了一个名为"foobar"的应用程序,它会在/var/log下生成foobar.log日志文件.现在,你想要将它的日志定向到rsysl ...

  5. MFC上下浮动与渐入渐出消息提示框实现

    类似QQ与360软件,消息提示有两种.上下浮动.渐入渐出. 1.上下浮动提示框实现 机制,定时器响应上下浮动消息. 主要API:MoveWindow. 源码如下UpDownTipDlg.h.UpDow ...

  6. ubuntu下编译内核驱动。

    目的: 1. 驱动热身.网上有很多类似的文章可供参考. 2. 在操作系统中, 编写这个设备的驱动. 3. 为写qemu的watchdog驱动练手. 有朋友问make的 watchdog驱动 需要什么准 ...

  7. #include <string>

    1 append(string T&);字符串拼接 2 c_str string.c_str是Borland封装的String类中的一个函数,它返回当前字符串的首字符地址. 3 empty() ...

  8. Java面试题之四

     十六.运行时异常与一般异常有何异同 Java提供了两类主要的异常:runtime exception和checked exception. 1.checked exception:这种异常也就是我们 ...

  9. oracle 与sql server 部分内置函数替换

    1,trunc--convert oracle: select trunc(sysdate) from dual   输出:2016/5/24 sql server:select CONVERT(va ...

  10. C++_基础_继承、多态

    内容: (1)子类中的拷贝构造和拷贝赋值 (2)多继承和虚继承 (3)多态的初识 (4)虚析构的特性和使用 (5)多态的底层实现 (6)纯虚函数.抽象类的概念 1.子类中的拷贝构造和拷贝赋值 子类中的 ...