C# - 多线程 之 进程与线程

转自原文 C# - 多线程 之 进程与线程

目录

  • 并行~并发
  • 进程~多进程
  • 线程~多线程
  • 线程池
  • 线程同步
  • 线程安全

回到顶部

并行~并发

并发

Concurrency逻辑上的同时发生,一个处理器(在不同时刻或者说在同一时间间隔内)"同时"处理多个任务。宏观上是并发的,微观上是按排队等待、唤醒、执行的步骤序列执行。并发性是对有限物理资源强制行使多用户共享(多路复用)以提高效率。

并行

Parallelism物理上的同时发生,多核处理器或多个处理器(在同一时刻)同时处理多个任务。并行性允许多个程序同一时刻可在不同CPU上同时执行。

Concurrency is not Parallelism.

并行一定是并发的、并发不一定是并行的。并行性是并发性的特例、并发性是并行性的扩展。

  • 并发:一个人(cpu)喂2个孩子(程序),轮换着每人喂一口,表面上两个孩子都在吃饭;
  • 并行:2个人喂2个孩子,两个孩子也同时在吃饭;

并行分解:以一种安全和可伸缩性的方式使程序并行化。

  • 数据并行;
  • 任务并行;
  • 混合方案:管道/流水线(合并数据和任务并行);

可伸缩性:目的就是做更多的事情,是衡量应用程序加速比大小的尺度之一。

其中,加速比是应用程序串行化与并行化之间所花费时间之比,表示并行化后的效率提升结果。

  • Amdahl定律:最小化串行工作
  • Gustafson定律:并行化增长的工作量、更大的问题域

关于Scalability Principle(可伸缩性原则)具体参考:可伸缩性原则; 可伸缩性的最差实践

参考:并行思维[I-III]

回到顶部

进程~多进程


1

命名空间:using System.Diagnostics;

进程

Process,是程序在计算机上的一次执行活动。运行一个程序、启动一个进程。程序是死的(静态的),进程是活的(动态的)。Windows系统利用进程把工作划分为多个独立的区域,每个应用程序实例对应一个进程。进程是操作系统分配和使用系统资源的基本单位。进程包含一个运行-ing应用程序的所有资源、进程(占用的资源)间相互独立。进程资源包括:

  • 一个进程堆;
  • 一个或多个线程;
  • 一个虚拟地址空间,该空间独立于其他进程的地址空间;
  • 一个或多个代码段,包括.dll中的代码;
  • 一个或多个包含全局变量的数据段;
  • 环境字符串,包含环境变量信息;
  • 其他资源,比如打开的句柄、其他的堆等; 

多进程

多任务:在同一计算机系统中,同一个时刻允许两个或两个以上的进程处于运行状态。现代操作系统是典型的基于抢占式调度机制的多任务操作系统。

特点

  • 进程间互相独立,可靠性高;
  • 进程之间不共享数据,没有锁问题、结构简单;
  • 需要跨进程边界,多进程调度开销较大;

时间片轮转进程调度算法:在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短,CPU轮流为多个进程服务(实际上任意时刻有且仅有一个进程占有CPU);

回到顶部

线程~多线程

线程快而进程可靠性高

  • 进程优点:编程、调试简单,可靠性较高;
  • 进程缺点:创建、销毁、切换速度慢,内存、资源占用大;
  • 线程优点:创建、销毁、切换速度快,内存、资源占用小;
  • 线程缺点:编程、调试复杂,可靠性较差;

1

命名空间:using System.Threading;

线程

Thread,轻量级进程,是进程的一个实体(线程本质上是进程中一段并发运行的代码),执行线程、体现程序的真实执行情况,是处理器上系统独立调度和时间分配的最基本的执行单元。同一进程的所有线程共享相同的资源和内存(共享代码,全局变量,环境字符串等),使得线程间上下文切换更快、可以在同一地址空间内访问内存。线程资源包括:

  • 堆栈:创建线程时生成,用于过程调用、中断、异常处理器和自动存储,对每个线程唯一;
  • 线程本地存储(TLS):指针数组,允许线程分配存储以创建自身特有的数据环境;
  • 上下文结构:由系统内核通过机器注册表值来维护;

一个进程可以有多个线程、一个线程必须有一个父进程,一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。

多线程

多任务可以由多进程完成,也可以由一个进程内的多线程完成。

  • 操作系统将CPU时间片分配给多个线程,每个线程在指定的时间片内处理任务。当前执行的线程在其时间片结束时被挂起、另一个线程继续运行。当系统从一个线程切换到另一个线程时,它会保存被抢先的线程的线程上下文、并重新加载线程队列中下一个线程的已保存的线程上下文;
  • CPU时间片很小,其长度取决于操作系统和处理器;

其中,若多个线程分属于不同的进程,宏观上多个进程同时执行、实现多任务处理。

优点

  • 共享进程资源,无需跨进程边界;
  • 通过网络与Web服务器和数据库通信;
  • 提高响应速度,新建线程去执行占用大量时间的(后台)操作;
  • 区分并分别执行具有不同优先级的任务;

缺点

  • 内存限制:系统将为进程、AppDomain对象、线程上下文信息分配内存;
  • 性能损失:线程的创建、销毁以及线程信息的跟踪占用处理器时间;
  • 线程同步:对资源的共享访问会造成冲突(死锁、争用条件);

辅助线程与主线程并行执行代码,多个线程并行工作完成多项任务、提高系统效率。具体地:

  • 执行耗时的任务或时间要求紧迫的任务,而不必占用主线程;
  • 桌面交互应用程序中执行“后台”任务,而使主线程继续保持对用户操作的响应;

多线程处理可以解决吞吐量、响应性等问题,但会导致资源共享问题、为单个资源分配多个线程也可能会导致同步问题。

参考:线程与线程处理 - msdn; .NET多线程总结和实例介绍

多线程 - 异步

相同:避免调用线程阻塞;

区别:(预备知识:拥有DMA直接内存访问功能的硬件在和内存进行数据交换时可以不消耗CPU资源)

  • 异步:DMA,硬件基础,I/O操作可以不消耗CPU资源;
  • 线程:OS,逻辑功能,运行和调度需要CPU资源;

参考:C#中异步和多线程的区别

其他

  • Java不能使用多进程,PHP不能使用多线程;

回到顶部

线程池

Thread Pool,C#/.Net线程池,即CLR线程池,用于在后台执行多个任务的线程的集合,通常用于服务器应用程序。CLR为每一个进程维护一个CLR线程池,池内的线程即CLR线程,一个CLR线程与一个Windows操作系统线程对应,默认属于后台线程(Background Thread)。分为两种:

  • 工作者线程(WorkerThread):管理CLR内部对象的运作、计算密集型任务;
  • IO线程(CompletionPortThread):访问外部资源并与其交互信息(为异步IO服务,异步功能的实现依赖IO线程);

CLR线程池在CLR初始化时不会立即建立线程、而是在应用程序要创建线程来处理任务时,线程池才会初始化一个线程。线程完成任务后,不会自行销毁、而是以挂起的状态返回到线程池,直到应用程序再次向线程池发出请求时,线程池里挂起的线程会被激活执行任务。

  • 线程重用:避免频繁创建、销毁线程的开销;
  • 具有最大线程数限制;

具体参见:C# - 多线程 之 Process与Thread与ThreadPool;  

回到顶部

线程同步

当一个线程操作内存时,其他线程都不能对这个内存地址进行操作、等待直到该线程完成操作。

目的:多个线程同时访问(读/写)共享数据时,防止数据被损坏

存在问题:同步锁的获得和释放

  • 实现比较繁琐、易出错;
  • 多线程异步执行,但有性能损失;
  • 每次只能允许一个线程访问资源;

实现方式和机制

  • 临界区Critical Section):通过对多线程的串行化、允许一个进程内的多线程访问公共资源或代码段,速度快、适合控制数据访问; 任意时刻只允许一个线程访问共享资源、其他试图访问该公共资源的线程将被挂起,直到访问临界区的线程离开、临界区被释放后,其他线程才可以抢占。
  • 互斥量Mutex):采用互斥对象机制,只有获得互斥对象的线程才有权限访问公共资源; 因为互斥对象只有一个、可以保证公共资源不会同时被多个线程访问,实现同一应用程序公共资源的安全共享(进程内的线程同步)以及不同应用程序公共资源的安全共享(跨进程的线程同步)。
  • 信号量Semaphore):允许多个线程同时访问同一资源,但要限制同一时刻访问同一资源的最大线程数;
  • 事件Event):采用线程间触发事件通知操作的方式保持线程同步,允许对多个线程的优先级比较;

其中,建议使用的线程同步手段: MonitorMutexManualResetEventAutoResetEvent。具体地:

参考:线程同步 - msdn

回到顶部

线程安全

线程安全主要考虑线程间共享变量的安全操作。同一进程的不同线程共享进程的内存空间(全局区、静态区、堆内存),线程的私有空间包括栈、寄存器、局部变量等。多线程访问时公共资源时,采用了加锁机制,避免数据不一致、数据污染等问题。

示例1:

示例2:

线程安全问题由全局变量及静态变量引起,Microsoft的.Net Framework类库(FCL)保证所有的静态方法都是线程安全的,但不保证实例方法是线程安全的。多线程对共享数据的只读访问不存在线程安全问题。

时间: 2024-10-18 03:41:01

C# - 多线程 之 进程与线程的相关文章

多线程编程(进程和线程)

多线程编程(进程和线程) 1.进程:指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程可以启动多个线程. 2.线程:指程序中一个执行流程,一个进程中可以运行多个线程. 一.创建线程(两种方式) 二.线程的5种状态( New,Runnable,Running,Block,Dead ): 三.线程的优先级 四.守护线程 /精灵线程/后台线程 五.方法 六.同步代码锁(synchronized) 一.创建线程(两种方式): 方式1:采用继承Thread的方法 第一,继承 Thre

Java多线程之 -- 进程和线程

Java多线程之 – 进程和线程 概念 进程 程序的动态执行过程 包括占用的资源(内存.CPU)和线程 线程 线程是程序中最小的执行单位 一个进程有多个线程 线程共享进程的资源 进程和线程的区分 我们可以想象为进程为班级而线程是邦奇中得每一个学生 线程之间的交互 互斥,类似于每一个学生都为了第一名而你争我让,线程也是,都想抢占CPU的资源 同步,当举行运动会的时候,大家都团结一心,彼此共享自己的资源 Thread.Runnable Thread Introduction Thread 是Java

VC++深入详解——第15章:多线程,进程,线程

1. 进程: (1)程序与进程 程序是计算机指令的集合,文件形式存储在计算机磁盘上. 进程是程序执行的一个实例,是一个程序在其地址空间的一次执行活动. 一个程序可以对应着多个进程. 进程是资源申请,调度看,独立运行的单位. (2)进程的组成: 内核对象:系统用来存放进程的相关统计信息的地方,是操作系统内部分配的一个内存块. 地址空间:包含所有可执行模块或DLL模块的代码和数据,还包含动态分配的内存空间,线程的栈和堆分配的空间. (3)进程不执行任何程序,进程只是线程的容器,是线程执行程序的环境.

day10-02_多线程之进程与线程的pid

一.多个线程之间PID的区别 主进程跟线程的pid是一样的 from threading import Thread from multiprocessing import Process import os def task(): print('%s is running' %os.getpid()) if __name__ == '__main__': t1=Thread(target=task,) t2=Thread(target=task,) t1.start() t2.start()

什么是进程And线程

原创 2015年02月01日 11:49:01 学习.net 时遇到了两个新词汇:进程和线程.书上的太深奥,就查了查资料,整合下,希望对大家有帮助. [比喻]:用手去抓苹果,很显然一根手指是不行,你需要至少两根手指才能抓起一个苹果. 在这里,用手抓苹果的事件就是一个进程.抓的过程可能需要多个手指协调,多个手指就是线程. [进程]:是操作系统中当前程序的一次执行. 要知道拥有单个CPU的电脑,在严格意义上,一个时间点上操作系统只能进 行同一个工作命令.由于计算机的运行速度快,在工作时可以运行一会A

进程、线程和多线程的概念

1. 什么是进程 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源,而一个进程又是由多个线程所组成的. 2. 什么是线程 线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针.程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数. 3. 什么是多线程 多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务. 4. 多线程的好处 可以提高CPU

Java多线程1:进程与线程概述

进程和线程 谈到多线程,就得先讲进程和线程的概念. 进程 进程可以理解为受操作系统管理的基本运行单元.360浏览器是一个进程.WPS也是一个进程,正在操作系统中运行的".exe"都可以理解为一个进程 线程 进程中独立运行的子任务就是一个线程.像QQ.exe运行的时候就有很多子任务在运行,比如聊天线程.好友视频线程.下载文件线程等等. 创建线程的方式 创建线程有两种方式: 1.继承Thread,重写父类的run()方法. public class MyThread00 extends T

进程、线程、多线程的网址集结(看)

面试总是会问这方面的内容,自己虽然知道一点点点点的概念,但是并不是很透彻的了解,这次,面试就挂在这个问题上了.哎.还是先提前写一下这个吧.进程和线程. 1.进程和线程 下面这个总结得挺好的. http://www.cnblogs.com/obama/archive/2013/04/12/3016509.html 2.多线程的讲解 http://blog.csdn.net/column/details/killthreadseries.html http://blog.csdn.net/morew

Java 多线程详解(二)------如何创建进程和线程

Java 多线程详解(一)------概念的引入:http://www.cnblogs.com/ysocean/p/6882988.html 在上一篇博客中,我们已经介绍了并发和并行的区别,以及进程和线程的理解,那么在Java 中如何创建进程和线程呢? 1.在 Windows 操作系统中创建进程 在 windows 操作系统中,我们创建一个进程通常就是打开某个应用软件,这便在电脑中创建了一个进程.更原始一点的,我们在命令提示符中来做(我们以打开记事本这个进程为例): 第一步:windows+R,