Linux_线程**

一.线程概念(也叫轻量级进程)

  1.在一个程序中的一条执行路线就叫做线程,更准确的说:线程是进程的一个内部的控制序列

  2.一个进程中至少有一个执行线程(控制序列)

二.线程和进程的区别

  1.进程是资源分配的基本单位,也是调度运行的基本单位,是系统中并发执行的单位。

  2.线程是进程中执行运算的最小单位

  3.线程共享进程的所有数据(内存和资源),但它也有自己一部分独立的数据(进程ID,一组寄存器,栈,上下文,errno,信        号屏蔽字,调度优先级)

  4.一个进程可以有多个线程,但一个线程只能属于一个进程

  5.线程是一种轻量级的进程,与进程相比,线程给操作系统带来侧创建、维护、和管理的负担要轻,意味着线程的代价或开销比      较小。

  6.线程没有地址空间,它在进程的地址空间中。线程的文本包含在进程的代码段中

  7.父子进程通过进程间通信进行通信,同一个进程间的不同线程通过读写数据通信

  8.同一个进程的线程处于相同的级别,线程可以对其他线程进行控制,可以销毁其他线程也可以销毁主线程,从而销毁进程

  9.子进程不能对其他的子进程施加控制,线程之间可以,也可以对主线程控制。

三.同一个进程中线程的共享资源

  1.同一个地址空间(进程的全局变量和函数,资源和环境)

  2.文件描述符表(代码和数据)

  3.每种信号的处理方式

  4.当前工作目录

  5.用户id和组id

四.线程的优点

  1.创建销毁一个新线程的代价比创建销毁一个新进程要小得多

  2.线程之间切换需要操作系统做的工作比进程之间切换要小的多

  3.线程占用的资源比进程少得多

  4.线程之间共享数据方便

  5.能充分利用多处理器的可并行数量

  6.在等待较慢的I/O操作结束的同时,其他线程还可以执行计算

  7.计算密集型应用,为了能在多处理系统上运行,将计算分解到多个线程中实现

  8.I/O密集型应用,为了提高性能呢,将I/O操作重叠,线程可以同时等待不同的I/O操作

五.线程的缺点

  1.性能损失  2.健壮性降低  3.缺乏访问控制  4.编程难度提高,调试难度提高  5.线程终止影响进程

六.进程控制API(需要链接pthread库)

  1.创建一个新线程

      1)头文件: #include <pthread.h>

      2)函数原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

      3)函数参数:第一个参数返回线程id,attr设置线程的属性(默认为NULL),第三个参数是线程启动后执行的动作(函数指                                    针),第四个参数是线程启动函数的参数

      4)返回值:成功返回0,失败返回错误码

      5)例子:

  1 #include <stdio.h>
  2 #include <pthread.h>
  3 #include <string.h>
  4 
  5 void arg(void){
  6     while(1){
  7         printf("small pthread!\n");
  8         sleep(1);
  9     }
 10 }
 11 
 12 int main(void){
 13     pthread_t tid;
 14     int ret=pthread_create(&tid,NULL,(void*)arg,NULL);
 15     if(ret!=0){
 16         printf("%s\n",strerror(ret));
 17         return 1;
 18     }
 19 
 20     for(;;){
 21         printf("main pthread!\n");
 22         sleep(2);
 23     }
 24     return 0;
 25 }

    查看线程id

   

     其中LWP是线程的id(可以通过gettid()获取),NLWP是线程组(多线程的进程)内线程的个数,可以看出以上程序中有两个线程,一个主线程,一个新创建的线程

     而且,线程组的tid就是主线程的tid,主线程tid就是当前进程的pid

     同一个线程组的线程,没有层次关系,所有的线程都是对等关系

  2.获取当前线程id

     1)头文件:#include <pthread.h>

     2)函数原型:pthread_t pthread_self(void);

     3)返回值:返回线程id

 3.线程终止(3种方法)

     a)在线程函数中return,但不适用于主线程,主线程return直接终止进程,相当于调用了exit 

     b)线程调用pthread_exit自杀

     c)一个线程可以调用pthread_cancel终止同一个进程中的另一个线程

     1)pthread_exit (自杀)

             o)头文件:#include <pthread.h>

             o)函数原型:void pthread_exit(void *retval);

             o)参数:retval不要指向一个局部变量(得到返回指针时若在栈上就已经销毁了,应该是全局或堆上内存)

             o)无返回值:线程结束无法再回到它的调用者

    2)pthread_cancel(他杀)

            o)头文件:#include <pthread.h>

            o)函数原型:int pthread_cancel(pthread_t thread);

            o)参数:要杀死的进程的id

            o)返回值:成功返回0,失败返回错误码

            o)此函数要求遇到取消点才执行,人为添加取消点void pthread_testcancel(void);这个函数的作用就是请求交付任何未决的取消请求

4.线程等待

    1)线程等待的作用

          a)已经退出的线程,其空间没有被释放,仍然在进程的地址空间中

          b)创建新的线程不会复用刚才退出的线程地址空间

  2)API(pthread_join)(只有阻塞方式)

          a)头文件:#include <pthread.h>

          b)函数原型:int pthread_join(pthread_t thread, void **retval);

          c)参数:thread等待线程的id ,retval指向一个指针,指向了线程的返回值

          d)返回值:成功返回0,失败返回错误码

          e)线程退出情况不同retval指向的单元存放的数据也不同(任何线程都可等待其他线程)

                   1>return返回,单元中存放线程函数的返回值

                   2>pthread_cancel异常终止,单元中存放常数PTHREAD_CANCELED(-1)

                   3>pthread_exit终止,存放传给pthread_exit的参数

                   4>对线程终止不感兴趣,写NULL

5.线程分离 (线程在终止时由系统自动释放资源,不能被其他线程回收或者杀死)

       1)线程分离的作用

              a)默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join的操作,否则无法释放资源,会造成内存泄漏

              b)如果不关心线程的返回值,join就多此一举了,这个时候可以告诉系统,当线程退出时,自动释放资源

       2)API

             1>头文件:#include <pthread.h>

             2>函数原型:int pthread_detach(pthread_t thread);

             3>参数:要分离的线程id  (可以分离自己,也可以分离其他线程)

             4>join与detach冲突

具体用例,请看之后博客--线程池

猜你喜欢

转载自blog.csdn.net/warrior_harlan/article/details/81199213
今日推荐