Linux多线程

进程与线程

进程的定义:进程是为了描述程序在并发执行时对系统资源的共享,所需的一个描述程序执行时动态特征的概念。进程是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配、调度和保护的独立单位。
  线程的定义:线程也成为轻量级进程,是进程中的一个运行实体,作为CPU的调度单位。一个进程由多个线程组成,线程与同属一个进程的其他的线程共享进程所拥有的全部资源。
同一进程内的所有线程除了共享全局变量外还共享:

  • 进程指令;
  • mm
  • 代码段(代码和常量);
  • 数据段(全局变量和静态变量)
  • 扩展段(堆存储
  • 打开的文件(即描述符);
  • 信号处理函数和信号处置;
  • 当前工作目录;
  • 用户ID和组ID。
    每个线程拥有各自的:
  • 线程ID;
  • 寄存器集合,包括程序计数器和栈指针;
  • (用于存放局部变量和返回地址);
  • errno;
  • 信号掩码;
  • 优先级。
    结构上的不同可以让我们更加了解进程和线程的相异之处:
    (1)进程是资源分配的基本单位;线程与资源分配无关,它属于某一个进程,并与进程内的其他线程共享进程的资源。
    (2)当进程发生调度时,不同的进程拥有不同的虚拟地址空间,而同一进程内的不同线程共享同一地址空间。
    (3)线程只由先关堆栈(系统栈或用户栈)寄存器和线程控制块组成。寄存器用来存储线程内的局部变量,但不能存储其他线程的相关变量。
    (4)进程切换时涉及有关资源指针的保存和地址空间的变化;线程切换时,由于处于同一进程内,所以不涉及资源信息的保存和地址空间的变化,从而减少了操作系统的时间开销

进程fork和vfork

fork(),子进程会拷贝父进程资源,但是不共享,彼此隔离。这里可以引申一下**写时拷贝技术**。

fock()
vfock(),子进程会拷贝父进程资源,但是内存不会拷贝,与父进程共享一个内存(物理地址)。
vfork()

pthread_join和pthread_death

一:关于join

join
  join是三种同步线程的方式之一。另外两种分别是互斥锁(mutex)和条件变量(condition variable)。
调用pthread_join()将阻塞自己,一直到要等待加入的线程运行结束, 或者调用了pthread_exit,或者被取消。
  可以用pthread_join()获取线程的返回值。
  一个线程对应一个pthread_join()调用,对同一个线程进行多次pthread_join()调用是逻辑错误。
join or detach
  线程分两种:一种可以join,另一种不可以。该属性在创建线程的时候指定。
joinable线程可在创建后,用pthread_detach()显式地分离。但分离后不可以再合并。该操作不可逆。
为了确保移植性,在创建线程时,最好显式指定其join或detach属性。似乎不是所有POSIX实现都是用joinable作默认。

二: pthread_detach

创建一个线程默认的状态是joinable, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收(退出状态码),所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid) 。但是调用pthread_join(pthread_id)后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当主线程为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),
  这时可以在子线程中加入代码 pthread_detach(pthread_self()) ,或者父线程调用
  pthread_detach(thread_id)(非阻塞,可立即返回) ,这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。

注意

  • 如果进程中的某个线程执行了pthread_detach(th),则th线程将处于DETACHED状态,这使得th线程在结束运行时自行释放所占用的 内存资源,同时也无法由pthread_join()同步,pthread_detach()执行之后,对th请求pthread_join()将返回错误 。
  • 一个可join的线程所占用的内存仅当有线程对其执行了pthread_join()后才会释放,因此为了避免内存泄漏,所有线程的终止,要么已设为DETACHED,要么就需要使用pthread_join()来回收 。
  • 用pthread_exit只会使主线程自身退出,产生的子线程继续执行;用return则所有线程退出。
      
      在进程主函数(main())中调用pthread_exit(),只会使主函数所在的线程(可以说是进程的主线程)退出;而如果是return,编译器将使其调用进程退出的代码(如_exit()),从而导致进程及其所有线程结束运行。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值