学习目标
1、掌握三种并发的方式:进程、线程、I/O多路复用
2、掌握线程控制及相关系统调用
3、掌握线程同步互斥及相关系统调用
学习资源
教材:第十一章《网络编程》简单过一下(刘念老师讲过了,我们只考试),教材:第十二章《并发编程》。
知识点总结
1、三种并发方式
构造并发程序的方法有三种:
进程
线程
I/O多路复用
进程:用内核来调用和维护,有独立的虚拟地址空间,显式的进程间通信机制。
线程:运行在一个单一进程上下文中的逻辑流。由内核进行调度,共享同一个虚拟地址空间。
I/O多路复用:应用程序在一个进程的上下文中显式地调度控制流。逻辑流被模型化为状态机。
2、线程控制及相关系统调用
socket编程中:线程是运行子进程上下文中的逻辑流。
线程与进程的不同:
线程的上下文切换要比进程的上下文切换快得多;
和一个进程相关的线程组成对等,独立于其他线程创建的线程。
主线程和其他线程的区别仅在于它总是进程中第一个运行的线程。
创建线程
pthread create:创建一个新的线程,在新线程的上下文中运行线程例程f。
新线程可以通过**pthread _self**获得自己的线程ID。
终止线程
一个线程的终止方式:当顶层的线程例程返回,线程会隐式地终止;
pthread_exit:线程显式地终止。
注:如果主线程调用**pthread _exit**,它会等待所有其他对等线程终止,然后再终止主线程和整个进程。
回收已终止线程的资源
pthread _join:阻塞,直到线程tid终止,回收已终止线程占用的所有存储器资源。
注:pthread _join只能等待一个指定的线程终止。
分离线程
在任何一个时间点上,线程是可结合的或者是分离的。一个可结合的线程能够被其他线程收回其资源和杀死;一个可分离的线程是不能被其他线程回收或杀死的。它的存储器资源在它终止时有系统自动释放。
默认情况下,线程被创建成可结合的,为了避免存储器漏洞,每个可集合的线程都应该要么被其他进程显式的回收,要么通过调用**pthread _detach被分离。
初始化线程 pthread _once允许初始化与线程例程相关的状态。once _control**变量是一个全局或者静态变量,总是被初始化为PTHREAD _ONCE _INIT。
3、C/S编程模型
- 客户端和服务器都是进程,C/S编程模型由一个服务器进程和一个或多个客户端进程组成。
服务器进程管理某种资源,通过操作这种资源来为它的客户端提供某种服务。基本操作为事务,一个客户端-服务器事务由四步组成:
(1)客户端向服务器发送请求,发起一个事务;
(2)服务器收到请求,操作资源;
(3)服务器给客户端发送一个响应,并等待下一个请求。 - (4)客户端收到响应并处理它。
教材学习中的问题和解决过程
I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态(对应空管塔里面的Fight progress strip槽)来同时管理多个I/O流. 发明它的原因,是尽量多的提高服务器的吞吐能力。
- 通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
Pthread是一种标准化模型,它用来把一个程序分成一组能够同时执行的任务。
什么场合会使用Pthread即线程?
1、 在返回前阻塞的IO任务能够使用一个线程处理IO,同时继续执行其他处理任务。
2、 在有一个或多个任务受不确定性事件,比如网络通信的可获得性影响的场合,能够使用线程处理这些异步事件同时继续执行正常的处理。
3、 如果某些程序功能比其他的功能更重要,可以使用线程以保证所有功能都出现,但那些时间密集型的功能具有更高的优先级。
从以上三点可以归纳位:在检查程序中潜在的并行性,也就是说找出能够同时执行任务时使用Pthread。但是以上已经介绍了Linux进程模型已经提供了执行多个进程的能力,已经可以进行并行或并发编程。可是线程能够让你对多个任务的控制程度更好,。使用资源更少,因为一个单一的资源,如全局变量,可以由多个线程共享。而且,在拥有多个处理器的系统上,多线程应用会比用多个
Linux线程实现方法
目前线程用两种方法实现:
(1)用户态线程:
用户线程是一个精细的软件工具,允许多线程的程序运行时不需要特定的内核支持。如果一个进程中的某一个线程调用了一个阻塞的系统调用,该进程就会被阻塞,当然该进程中的其他所有线程也同时被阻塞,因此UNIX使用了异步I/O机制。这种机制主要的缺点在于在一个进程中的多个线程的调度中无法发挥多处理器的优势(如上述的阻塞情况)。
其优点包括:
1、某些线程操作的系统消耗大大减少。比如,对属于同一个进程的线程之间进行调度切换时不需要调用系统调用,因此将减少额外的消耗,往往一个进程可以启动上千个线程也没有什么问题。
2、 用户态线程的实现方式可以被定制或修改以适应特殊应用的要求。这对于多媒体实时过程等尤其有用。另外,用户态线程可以比核心态线程实现方法的默认情况支持更多的线程。
(2)核心态线程
这种线程的实现方法允许不同进程中的线程按照同一相对优先调度方法进行调度。这有利于发挥多处理器的并发优势。目前线程主要的实现方法是用户态线程。有几个研究项目已经实现了一些核心态线程的形式。其中比较著名的是MACH分布式操作系统。通过允许用户代码对内核线程调度的参与,该系统将用户态和核心态两种线程实现方法的优点结合了起来。通过提供这样一个两级调度机制,内核在保留了对处理器时间分配的控制的同时,也使一个进程可以充分利用多处理器的优势。
四、Linux对超线程技术支持
超线程技术是Intel 公司的创新设计,藉由在一颗实体处理器中放入二个逻辑处理单元,让多 线程软件可在系统平台上平行处理多项任务,并提升处理器执行资源的使用率。使用这项技术,处理器的资源利用率可获得提升,大大增加处理的传输量。 超线程使得单个的处理器可以伪装成操作系统看来二个或更多的多个处理器。Linux内核在2.4.17发布中开始包含对Intel P4处理器的超线程(Hyperthreading)的支持(2.4最初的发布版本中不支持它)。Linux是第一个把超线程特性引入市场的操作系统,尽管早在一年前Intel就发布了兼容的处理器。它包括了以下增强技术:
-
128 字节锁对齐。
-
螺旋等待循环优化 。
-
基于非执行的延迟循环 。
-
检测支持超线程的处理器,并启动逻辑处理器,如同该机器是SMP(多处理器构架) 。
-
MTRR 和微码更新(Microcode Update)驱动程序中的串行化,因为它们影响共享状态 。
-
在逻辑处理器上的调度发生之前,当系统空闲时对物理处理器上的调度进行优先级排序时,对调度程序进行优化 。
代码托管
https://gitee.com/shadowsombra/java-basti-is-tip/tree/master/week8