多线程编程<一>

来源:互联网 发布:七彩服装进销存软件 编辑:程序博客网 时间:2024/04/28 00:05
一、理解线程

1.进程与线程联系
     线程:线程也是一个执行流,线程在进程内部运行
     1.对一个进程来讲,每个进程都有个PCB,且每个进程均有自己的独立地址空间,进程的地址空间是00-FF,4G(32位下),再从地址空间由MMU和页表转化为物理内存--> 环境变量区 栈区 堆区 静态区 
     进程强调资源独占,进程间不受影响(fork的子进程和父进程代码共享数据独立;vfork子进程和父进程共享地址空间)。而线程强调资源共享
     2. 线程是操作系统调度的基本单位,进程是承担分配系统资源的基本单位。
     3.进程能共享地址空间,让他们使用这份地址空间的一部分资源,此时这两个进程就是在同一份地址空间下的两个线程
     4.进程刚创建时只有一个执行流,一个PCB,地址空间也分配好,线程就不用再分配,直接使用进程分配好的资源。
     linux下,一个进程就是一个独占资源的线程,即在这个地址空间仅有一个执行流,linux下的进程均为轻量级进程(进程可以理解为是线程,可以理解为linux下均为线程),进程和线程均叫做pcb
(windows下,TCB(线程控制块))

2.线程独有部分
1.由于线程是调度的基本单位,线程必须要有自己独立的硬件上下文信息,方便上下文的切换
2.栈空间。每个线程都会执行各个分支,会出现各种临时变量(栈),所以每个线程都有自己的私有栈,这样线程之间的临时变量就不会相互影响
3.信号屏蔽字私有
4.调度优先级
5.线程id
6.errno变量

3.线程共享部分
1.文件描述符表
2.每种信号的处理方式
3.当前工作目录
4.用户id和组id

二、线程控制
1、创建控制

返回值:成功返回0,失败返回错误号
创建线程示例
*注意:打印出的线程号仅在这个函数有效
*命令 ps -al可打印出当前所有线程

2.终止线程
终止线程有三种方式:
  • 从线程函数return,如果在主线程调用return相当调用exit,终止进程
  • 线程调用pthread_exit(退出码)终止自己
  • 线程可以调用pthread_cancel(id)终止同一进程的另一个线程。
*注意:如果任意线程调用exit或_exit,则整个进程的所有线程都终止
①pthread_exit函数

②pthread_cancel函数

*注意:pthread_exit或者return返回的指针所指向的内存单元必须是全局或者用malloc分配的,不能再线程函数的栈上分配,因为线程的栈私有,且其他线程得到这个返回指针时线程函数已经退出。

3.线程等待
     在pthread_exit函数的参数中retval是void*类型,其他线程可以调用pthread_join获得这个指针。
pthread_join函数:
     调用该函数的线程将挂起等待,知道id为thread的线程终止。

返回值:成功返回0,失败返回错误号
1.如果thread线程通过return返回,value_ptr所指向的单元存放的是thread线程函数的返回值。
2.如果thread线程被别的线程调用pthread_cancel异常终止,value_ptr所指向的单元存放常数PTHREAD_CANCELED。
3.如果thread线程是自己调用pthread_exit终止,value_ptr所指向的单元存放传给pthread_exit的参数。
线程等待


心得:
1,线程的等待只有阻塞,进程等待有阻塞和非阻塞
2.进程的退出码在0-255之间,线程的退出码可以在255以上不过最好和进程保持一致
3.线程必须等待(内存泄漏),进程里也需要等待(僵尸进程)
4.如果一个线程是被取消的,退出码为-1(定义为宏PTHREAD_CANCEL),如果是exit或return的退出码为自己设定的值
三、线程分离
     在任何一个时间点上,线程是可结合的或者可分离的,一个可结合的线程能够被其他线程收回其资源和杀死。在其他线程回收之前,它的存储资源时不释放的。相反,一个分离的线程是不能被其他线程回收或者杀死的,它的存储资源在它终止时自动释放
     一般情况下,线程终止后,其终止状态一直保留到其他线程调用pthread_join获取它的状态为止。但是线程可以被设置为detach状态,这样线程一旦终止就立即回收它占用的所有资源,而不是保留终止状态。不能对一个已经detach的线程调用pthread_join,这样调用将返回EINVAL。
     对一个尚未detach的线程调用pthread_join或pthread_detach都可以把线程置为detach状态。对一个线程不能同时调用两次pthread_join。同样,如果对一个线程调用了pthread_join也就不能调用pthread_join了

成功返回0,失败返回错误号
注意:
  1. 默认情况下,线程被创建成可结合的。为了避免存储器泄漏,每个可结合的线程都需要显式的回收,即调用pthread_join或者pthread_detach
  2. 调用pthread_join后,如果线程没有运行结束,调用者会被堵塞。在子线程加入代码pthread_detach(pthread_self())或者父线程调用pthread_detach(thread_id)(非阻塞,可立即返回),这将子线程的状态设为分离,这样,该线程运行结束后会自动释放所有资源
0 0
原创粉丝点击