Skip to content

Latest commit

 

History

History

5_MultiThread

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

多线程、多进程

[TOC]

多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。一般情况下,两种类型的多任务处理:基于进程和基于线程。

  • 基于进程的多任务处理是程序的并发执行。
  • 基于线程的多任务处理是同一程序的片段的并发执行。

多线程程序包含可以同时运行的两个或多个部分。这样的程序中的每个部分称为一个线程,每个线程定义了一个单独的执行路径。

currently just materials, need efforts to manage them into an assistant or a teaching file .

所谓进程,表示在计算机系统中,一个程序的执行以及对资源分配的基本单位,简言之进程就是一段程序的执行过程。它是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。在一个进程中,会包含多个线程,一个进程中的任何线程,均可以利用这个进程中的所有资源。线程是独立运行和独立调度的基本单位,由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统多个程序间并发执行的程度。线程解决的最大问题就是它可以很简单地表示共享资源的问题,这里说的资源指的是存储器资源,资源最后都会加载到物理内存,一个进程的所有线程都是共享这个进程的同一个虚拟地址空间的,也就是说从线程的角度来说,它们看到的物理资源都是一样的,这样就可以通过共享变量的方式来表示共享资源,也就是使用直接共享内存的方式解决了线程通信的问题。而线程也表示一个独立的逻辑流,这样就完美解决了进程的一个大难题在一个程序中,为了提高系统运行效率以及资源利用率,我们往往需要计算机系统同时处理多项任务,因此在这时候将会使用多线技术程来同步完成多项任务。

在Linux中,进程或线程的同步或互斥一般有临界区、互斥量、信号量、事件这四种控制方法。

①临界区

每个进程中,访问临界资源的代码段被称为临界区,所谓临界资源,即每次仅允许一个进程使用的共享资源。在进程中,每次只允许一个进程进入临界区,一旦有进程进入,其他进程则无法再进入。因此可以理解为无论是硬件还是软件资源,如果有多个进程存在,则对临界区的访问一定是互斥的。在Linux系统中,如果在一个临界区中同时被多个线程试图访问,那么每次依然只能通过一个线程,而其他试图访问的线程都会被挂起,待之前进入临界区的线程离开后,再令下一个被挂起的线程进入,直至所有线程访问完毕,这样就可以保证不会在同一时间出现多个线程同时访问共享资源。临界区在使用时,通常以CRITICAL_SECTION结构对象保护共享资源,该结构对象需要用InitializeCriticalSection()函数初始化后才可使用,在使用时我们可以调用EnterCriticalSection()和LeaveCriticalSection()这两个函数去标记和释放一个临界区,而且还需要保证所有线程中试图访问该共享资源的代码块都处于临界区的保护中。

②互斥量

在Linux中,系统提供了一种名为mutex的互斥锁,也叫做互斥量。互斥量的作用是为了保护临界区代码,在同一时刻只能有一个线程持有该锁,从而保证每次只有一个线程访问临界区代码。使用互斥量的意义就是为了实现原子操作,通过将资源的访问变为互斥操作,而后与时序竞态有关的错误也不会在产生了。由于互斥量本质是串行执行,如果有很多个线程需要频繁的加锁同一个互斥量,那么这些线程的大部分时间都将处于等待中,这样一来对整体系统的性能是非常不利的。互斥量需要时间来加锁和解锁,所以锁的数量应该尽量少,每个锁所保护的区域应该尽量的大。然而如果互斥量保护的数据包含彼此无关的代码片段,则可以将大的互斥量分解为几个小的互斥量来提高性能。这样,任意时刻需要小互斥量的线程减少,线程等待的时间就会减少,所以为了考虑系统的性能,锁的数量又需要足够多,每个锁保护的区域应该足够大。因此,在实际的设计中,需要找到合适的平衡关系。

③信号量

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,它负责协调各个线程,以保证它们能够正确、合理的使用公共资源。信号量通常用于多线程多任务中的同步,一个线程完成了某一个工作后就通过信号量告诉别的线程,别的线程再进行其他的动作。因此,信号量不一定是锁定某一个资源,而是流程上的概念。信号量与互斥量有着本质的区别,它们的应用目的截然相反,互斥量用于线程的互斥,而信号量用于线程的同步;互斥量值只能为0/1,信号量值可以为非负整数;互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。信号量通过一个计数器控制对共享资源的访问,信号量的值是一个非负整数,所有通过它的线程都会将该整数减1。如果计数器大于0,则访问被允许,计数器减1;如果为0,则访问被禁止,所有试图通过它的线程都将处于等待状态。计数器计算的结果是允许访问共享资源的通行证。因此,为了访问共享资源,线程必须从信号量得到通行证,如果该信号量的计数大于0,则此线程获得一个通行证,这将导致信号量的计数递减,否则,此线程将阻塞直到获得一个通行证为止。当此线程不再需要访问共享资源时,它将会释放该通行证,这导致信号量的计数递增,如果另一个线程正在等待通行证,则那个线程将在此时获得通行证。

④事件

事件是用来通知线程有一些事件已发生,从而启动后继任务的开始。事件对象也可以通过通知操作的方式来保持线程的同步,并且可以实现不同进程中的线程同步操作

1. 多线程编程

1.1 多线程基础

1.2 生产者-消费者

示例程序: producer_consumer

参考资料:

2. 多进程

2.1 多进程与管道

示例程序: process_pipe

3. 协程 (coroutine)

示例程序: coroutine

4. 多线程实现框架

基于zmq的线程通讯框架

官方教程

特点:

  • 简单
  • 线程、进程、远端同构化,可以同时掌握基于zmq的通讯框架
  • 通过私有数据避免锁、信号量等复杂机制的使用,所有的数据交流通过线程安全的zmq_context进行

参考资料: