浅谈.NET下的多线程和并行计算(一)前言

简介: 作为一个ASP.NET开发人员,在之前的开发经历中接触多线程编程的机会并不是很多,但是随着.NET 4.0的发布临近,我越来越感受到未来的1-2年中并行计算将会有很大的应用。于是决定通过写日志的方式来总结一下.NET 3.5下的多线程编程进而引入.NET 4.0提供的新的并行库以及新的并行编程模式和编程的思维方式。

作为一个ASP.NET开发人员,在之前的开发经历中接触多线程编程的机会并不是很多,但是随着.NET 4.0的发布临近,我越来越感受到未来的1-2年中并行计算将会有很大的应用。于是决定通过写日志的方式来总结一下.NET 3.5下的多线程编程进而引入.NET 4.0提供的新的并行库以及新的并行编程模式和编程的思维方式。

个人觉得在日常的编程中对于ASP.NET程序员来说使用多线程编程不是很多,其实我们无时无刻不在享受多线程的优势。首先,WEB服务器环境就是一个多线程环境,每一个请求都是独立的线程,如果没有多线程很难想象只能同步处理一个请求的WEB服务器有什么用,类似,我们的数据库也应该是一个多线程环境。对于Windows应用程序的程序员来说恐怕就很难不接触多线程了,最简单的就是我们会新开线程去做一些耗时的操作,这样就可以避免UI停止响应,在操作结束后再把操作结果应用在主线程的控件上。虽然说这样的应用是多线程,甚至很多程序员习惯什么操作都新开一个线程去做,但是我觉得这样的多线程应用的思维还停留在单核时代,在多核时代,我们确实可以让任务实际的并行执行而不是看上去并行执行。

首先来说说概念,进程和线程的基本的概念不用多说,自然我们也能理解一个进程至少包含一个线程。通过在一个进程中开启多个线程,我们就可以让一个程序在同一时间看上去能做多个事情,比如可以在接受用户响应的时候进行一些计算。在以前处理器往往只有一个核心,也就是说在同一时间,处理器只能做一件事情。那么怎么实现之前说的多个线程同时执行呢。其实这个同时只是表面上看上去同时,本质上多个线程依次占用处理器的若干时间片,大家轮流使用其资源,由于这个时间片非常短,所以在一个长的时间看来似乎是几个线程同时得到了执行。

举一个生动的例子,我们经常看到有一些画家能同时在一个画布上画两个不同的图片,一个画人一个画房子,最后一起完成这个画。但仔细看的话发现,他是两手拿了两只画笔,在这里画一笔那里画一笔,在同一时间其实也只有一只笔在画。这个画家应该也像普通人一样是单核的,只是线程切换比较快罢了。我经常在打电话的时候和网友进行聊天,在同一时间做两件事情,但是这样很费脑子,在打字前我要回忆一下刚才聊天的内容,然后输入聊天的文字,然后再去回想一下刚才那哥们说了啥,在电话里面回他一句,这种回忆的工作就是准备线程的上下文,交给脑子去处理。虽然同一时间是做了两件事情,但是这个上下文的准备工作也浪费了点时间,如果我在打电话网络聊天的同事在去做第三件事情比如看电影,那我估计就不行了。所以,线程也不能开的很多,特别对于人脑来说。但是对于电脑处理器来说就不一样了,你只要准备好数据和指令他执行就是了,至于这些事情来自几件事情它不关心,24小时一秒都不浪费在执行指令完全没问题,当然你也可以让它闲着。

您可能会想了,既然线程切换需要时间,那么我们开两个线程执行两个任务不是还没有一个一个执行来的快吗?其实即使对于单核的处理器都不一定,因为在实际的应用中我们的任务往往不可能从头计算到尾一直占用处理器资源,在很多时候我们要等待IO响应或用户的响应,如果只是一个线程做事情的话处理器太闲了。对于现在多核的处理器来说,在同一时刻理论上可以在每一个处理器上都并行执行指令,我们就更需要利用多线程来提高运算速度了。当然也不是说一个任务要执行10秒,我们在双核的机器上并行执行这个任务只需要5秒了,那是因为很多时候这个任务很难划分成两个分支来并行执行,如果每个指令都要依靠上个指令的执行结果,那么这样的操作很难在多个处理器上并行执行。但是,我们可以这样想,至少如果有两个这样任务的话,我们就可以完全利用多个处理器的优势来并行执行了。

但是也不是多可以随便的开线程,每一个线程默认情况下都会占用1M的栈空间(对于普通应用程序来说),在32位Windows平台下可以给一个用户进程使用的程序最大在2G,那么也就是说在程序中使用的线程不能超过2000个,在实际测试中可以发现一般来说开1930左右个线程就会收到内存不足的异常,其实这个数量是绝对够用的,即使复杂的Outlook2007程序一般也只用了50个不到的线程(可以在任务管理器中观察到)。

在不得已的情况下很多人都不太会去使用多线程也是有原因的,一是因为多线程编程复杂,我们也习惯了一行一行代码执行的编程模式,对于一个好的多线程程序来说,要尽量分割任务让它在多个线程中使用以利用到多个处理器核。还有就是多个线程使用相同资源的话还要考虑资源的锁定以免产生数据的不一致。锁定/事务/并发的概念在数据库中也是非常常见的。二是因为调试困难,特别是一个线程的执行依赖其它线程的执行。三是因为多线程的程序随着环境的变化(处理器/操作系统)可能执行的性能还不一定相同,如果只针对某个环境进行编程可能还不能充分利用多处理器的优势。比如我们对一个任务划分成2个线程并行执行,那么对于四核的处理器来说,划分成4个线程并行执行会不会更合理呢,说实话我也举的这事挺难说的?还有,我们的编程基于.NET框架,而其本质还是使用的是操作系统的线程,操作系统中本来就有很多进程运行着,处理器是大家的处理器,不是专供我们程序使用的,在这么一个鱼龙混杂的环境,我们的程序究竟是不是会表现的如我们预期那样,也很难说。

多线程好,多线程难,本系列文章也只能在一个比较浅显的层次来谈谈如何在.NET框架中进行多线程编程,以及一些常见应用(比如Windows应用)中多线程的典型应用。本系列文章预计会有30篇这样的规模,希望对大家有帮助。

作者: lovecindywang
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
27天前
|
Java API 调度
【JavaEE】——多线程(join阻塞,计算,引用,状态)
【JavaEE】——多线程,join,sleep引起的线程阻塞,多线程提升计算效率,如何获取线程的引用和状态
|
6月前
|
Python
解锁Python并发新世界:线程与进程的并行艺术,让你的应用性能翻倍!
【7月更文挑战第9天】并发编程**是同时执行多个任务的技术,提升程序效率。Python的**threading**模块支持多线程,适合IO密集型任务,但受GIL限制。**multiprocessing**模块允许多进程并行,绕过GIL,适用于CPU密集型任务。例如,计算平方和,多线程版本使用`threading`分割工作并同步结果;多进程版本利用`multiprocessing.Pool`分块计算再合并。正确选择能优化应用性能。
45 1
|
2月前
|
开发框架 Java .NET
.net core 非阻塞的异步编程 及 线程调度过程
【11月更文挑战第12天】本文介绍了.NET Core中的非阻塞异步编程,包括其基本概念、实现方式及应用示例。通过`async`和`await`关键字,程序可在等待I/O操作时保持线程不被阻塞,提高性能。文章还详细说明了异步方法的基础示例、线程调度过程、延续任务机制、同步上下文的作用以及如何使用`Task.WhenAll`和`Task.WhenAny`处理多个异步任务的并发执行。
|
2月前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
3月前
|
并行计算 安全 Java
Python 多线程并行执行详解
Python 多线程并行执行详解
109 3
|
5月前
|
算法 Java
JUC(1)线程和进程、并发和并行、线程的状态、lock锁、生产者和消费者问题
该博客文章综合介绍了Java并发编程的基础知识,包括线程与进程的区别、并发与并行的概念、线程的生命周期状态、`sleep`与`wait`方法的差异、`Lock`接口及其实现类与`synchronized`关键字的对比,以及生产者和消费者问题的解决方案和使用`Condition`对象替代`synchronized`关键字的方法。
JUC(1)线程和进程、并发和并行、线程的状态、lock锁、生产者和消费者问题
|
5月前
|
前端开发 JavaScript 大数据
React与Web Workers:开启前端多线程时代的钥匙——深入探索计算密集型任务的优化策略与最佳实践
【8月更文挑战第31天】随着Web应用复杂性的提升,单线程JavaScript已难以胜任高计算量任务。Web Workers通过多线程编程解决了这一问题,使耗时任务独立运行而不阻塞主线程。结合React的组件化与虚拟DOM优势,可将大数据处理等任务交由Web Workers完成,确保UI流畅。最佳实践包括定义清晰接口、加强错误处理及合理评估任务特性。这一结合不仅提升了用户体验,更为前端开发带来多线程时代的全新可能。
138 1
|
4月前
|
SQL 存储 监控
SQLServer事务复制延迟优化之并行(多线程)复制
【9月更文挑战第12天】在SQL Server中,事务复制延迟会影响数据同步性。并行复制可通过多线程处理优化这一问题,提高复制效率。主要优化方法包括:配置分发代理参数、优化网络带宽、调整系统资源、优化数据库设计及定期监控维护。合理实施这些措施可提升数据同步的及时性和可靠性。
144 0
|
5月前
|
算法 Java
JDK版本特性问题之想控制 G1 垃圾回收器的并行工作线程数量,如何解决
JDK版本特性问题之想控制 G1 垃圾回收器的并行工作线程数量,如何解决
|
6月前
|
SQL 安全
线程操纵术并行策略问题之调整并行流的并行度问题如何解决
线程操纵术并行策略问题之调整并行流的并行度问题如何解决