c# 多线程学习笔记 (一)基本概念


面试中总不可避免的会问到一些多线程的问题。尽管项目中也会实践一些,但是一方面可能也是不全面,另一方面如果时间太久了,可能有些处理问题的规则也会忘记。利用这段时间把多线程的问题分以下几个方面加以整理。因为我目前主要是用c#语言,因此一些实践例子也用c#来实现。

以下文章主要参考了

http://blog.csdn.net/morewindows/article/details/7392749博客中秒杀多线程系列的文章。

(一)  基本概念

(二)  互斥与同步

(三)  原子操作

(四)  生产者,消费者

(五)  读者写者

(六)  死锁及解决

(七)  c#中其它和多线程相关的API

 

 

(一)基本概念

1. 进程

进程是用于组织资源的单位,进程将相关的资源组织在一起,这些资源包括:内存地址空间,程序,数据等,将这些以进程的形式组织起来可以使得操作系统管理这些资源更为容易。

进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源集合。每个进程都被赋予了一个虚拟地址空间,确保一个进程使用的代码和数据无法由另一个进程进行访问(除非利用分布式计算方式)。一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。进程可以理解为一个程序的基本边界。

2.线程 

作为windows概念,线程的职责是对cpu进行虚拟化。Windows为每个进程都提供了该进程专业的线程(功能相当于一个CPU,可将线程理解为一个逻辑CPU)

线程虽然共享进程中的大多数资源,但线程也需要自己的一些资源,比如:用于标识下一条执行指令的程序计数器,一些容纳局部变量的寄存器,以及用于表示执行的历史的栈。

在.NET应用程序中,都是以Main()方法作为入口的,当调用此方法时系统就会自动创建一个主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状 态信息。

3. 线程与进程的区别

从上面两个概念来看,进程和线程本来就不是一种类似的概念。

在Mac、Windows NT等采用微内核结构的操作系统中,进程的功能发生变化:它只是资源分配的单位,而不再是调度运行的单位。在微内核系统中,真正调度运行的基本单位是线程。因此,实现并发功能的单位是线程。

进程有独立的地址空间,比如在linux下面启动一个新的进程,系统必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种非常昂贵的多任务工作方式。而运行一个进程中的线程,它们之间共享大部分数据,使用相同的地址空间,因此启动一个线程,切换一个线程远比进程操作要快,花费也要小得多。当然,线程是拥有自己的局部变量和堆栈(注意不是堆)的,比如在windows中用_beginthreadex创建一个新      进程就会在调用CreateThread的同时申请一个专属于线程的数据块(_tiddata)。

线程之间的通信比较方便。统一进程下的线程共享数据(比如全局变量,静态变量),通过这些数据来通信不仅快捷而且方便,当然如何处理好这些访问的同步与互斥正是编写多线程程序的难点。而进程之间的通信只能通过进程通信的方式进行。

线程的执行与进程是有区别的。每个独立的线程有有自己的一个程序入口,顺序执行序列和程序的出口,但是线程不能独立执行,必须依附与程序之中,由应用程序提供多个线程的并发控制。

总而言之:进程是组织资源的最小单位,而线程是安排CPU执行的最小单位。

参考 :

http://blog.csdn.net/wilsonke/article/details/7616984

http://www.cnblogs.com/CareySon/archive/2012/05/04/ProcessAndThread.html

http://www.cnblogs.com/obama/archive/2013/04/12/3016509.html

 

4. 应用程序域:

应用程序域(AppDomain)是一个程序运行的逻辑区域,它可以视为一个轻量级的进程,.NET的程序集正是在应用程序域中运行的,一个进程可 以包含有多个应用程序域,一个应用程序域也可以包含多个程序集。在一个应用程序域中包含了一个或多个上下文context,使用上下文CLR就能够把某些 特殊对象的状态放置在不同容器当中。

5. 多线程

多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

在单CPU系统的一个单位时间(time slice)内,CPU只能运行单个线程,运行顺序取决于线程的优先级别。如果在单位时间内线程未能完成执行,系统就会把线程的状态信息保存到线程的本地 存储器(TLS) 中,以便下次执行时恢复执行。而多线程只是系统带来的一个假像,它在多个单位时间内进行多个线程的切换。因为切换频密而且单位时间非常短暂,所以多线程可 被视作同时运行。

适当使用多线程能提高系统的性能,比如:在系统请求大容量的数据时使用多线程,把数据输出工作交给异步线程,使主线程保持其稳定性去处理其他问题。但需要注意一点,因为CPU需要花费不少的时间在线程的切换上,所以过多地使用多线程反而会导致性能的下降。

 

其实多线程的切换是个极其消耗资源的工作,这点可以从《CLRvia C#》 by Jeffrey Richter 中关于线程的介绍可以看到。

 

6.线程安全

多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。

发布了32 篇原创文章 · 获赞 7 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/mochounv/article/details/52217297