Welcome

首页 / 软件开发 / .NET编程技术 / 并发危险:解决多线程代码中的11个常见的问题

并发危险:解决多线程代码中的11个常见的问题2011-10-30 msdn Joe Duffy本文将介绍以下内容:

基本并发概念

并发问题和抑制措施

实现安全性的模式

横切概念

本文使用了以下技术:

多线程、.NET Framework

并发现象无处不在。服务器端程序长久以来都必须负责处理基本并发编程模型,而随着多核处理器的 日益普及,客户端程序也将需要执行一些任务。随着并发操作的不断增加,有关确保安全的问题也浮现出 来。也就是说,在面对大量逻辑并发操作和不断变化的物理硬件并行性程度时,程序必须继续保持同样级 别的稳定性和可靠性。

与对应的顺序代码相比,正确设计的并发代码还必须遵循一些额外的规则。对内存的读写以及对共享 资源的访问必须使用同步机制进行管制,以防发生冲突。另外,通常有必要对线程进行协调以协同完成某 项工作。

这些附加要求所产生的直接结果是,可以从根本上确保线程始终保持一致并且保证其顺利向前推进。 同步和协调对时间的依赖性很强,这就导致了它们具有不确定性,难于进行预测和测试。

这些属性之所以让人觉得有些困难,只是因为人们的思路还未转变过来。没有可供学习的专门 API, 也没有可进行复制和粘贴的代码段。实际上的确有一组基础概念需要您学习和适应。很可能随着时间的推 移某些语言和库会隐藏一些概念,但如果您现在就开始执行并发操作,则不会遇到这种情况。本文将介绍 需要注意的一些较为常见的挑战,并针对您在软件中如何运用它们给出一些建议。

首先我将讨论在并发程序中经常会出错的一类问题。我把它们称为“安全隐患”,因为它们很容易发 现并且后果通常比较严重。这些危险会导致您的程序因崩溃或内存问题而中断。

当从多个线程并发访问数据时会发生数据争用(或竞争条件)。特别是,在一个或多个线程写入一段 数据的同时,如果有一个或多个线程也在读取这段数据,则会发生这种情况。之所以会出现这种问题,是 因为 Windows 程序(如 C++ 和 Microsoft .NET Framework 之类的程序)基本上都基于共享内存概念, 进程中的所有线程均可访问驻留在同一虚拟地址空间中的数据。静态变量和堆分配可用于共享。

请考虑下面这个典型的例子:

static class Counter {  internal static int s_curr = 0;  internal static int GetNext() {    return s_curr++;  }}