知识大全 .NET 4并行编程之共享数据问题和解决概述

Posted

篇首语:上如阶尽管费力,却一步比一步高。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 .NET 4并行编程之共享数据问题和解决概述相关的知识,希望对你有一定的参考价值。

.NET 4并行编程之共享数据问题和解决概述  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  在开始之前 首先 我们来看一个很有趣的例子

  class BankAccount

  

  public int Balance

  

  get;

  set;

  

  

  class App

  

  static void Main(string[] args)

  

  // create the bank account instance

  BankAccount account = new BankAccount();

  // create an array of tasks

  Task[] tasks = new Task[ ];

  for (int i = ; i < ; i++)

  

  // create a new task

  tasks[i] = new Task(() =>

  

  // enter a loop for balance updates

  for (int j = ; j < ; j++)

  

  // update the balance

  account Balance = account Balance + ;

  

  );

  // start the new task

  tasks[i] Start();

  

  // wait for all of the tasks to plete

  Task WaitAll(tasks);

  // write out the counter value

  Console WriteLine( Expected value Counter value:

   account Balance);

  // wait for input before exiting

  Console WriteLine( Press enter to finish );

  Console ReadLine();

  

  

   个task 每个task都是把BankAccount Balance自增 次 之后代码就等到 个task执行完毕 然后打印出Balance的值 大家猜想一下 上次的代码执行完成之后 打印出来的Balance的结果是多少?

  J结果确实和大家猜想的一样 结果不等于 每次执行一次上面的代码 都会得到不同的结果 而且这些结果值都在 左右 如果运气好 可能看到有那么一两次结果为 为什么会这样?

  下面就是本篇和接下来的几篇文章要讲述的内容

   数据竞争

  如果大家对多线程编程比较熟悉 就知道上面情况的产生是因为 共享数据竞争 导致的(对多线程不熟悉不清楚的朋友也不用担心) 当有两个或者更多的task在运行并且操作同一个共享公共数据的时候 就存在潜在的竞争 如果不合理的处理竞争问题 就会出现上面意想不到的情况

  下面就来分析一下 上面代码的情况是怎么产生的

  当在把account对象的Balance进行自增的时候 一般执行下面的三个步骤

  读取现在account对象的Balance属性的值

  计算 创建一个临时的新变量 并且把Balance属性的值赋值给新的变量 而且把新变量的值增加

  把新变量的值再次赋给account的Balance属性

  在理论上面 上面的三个步骤是代码的执行步骤 但是实际中 由于编译器 NET 运行时对自增操作的优化操作 和操作系统等的因素 在执行上面代码的时候 并不一定是按照我们设想的那样运行的 但是为了分析的方便 我们还是假设代码是按照上面的三个步骤运行的

  之前的代码每次执行一次 执行代码的计算机就每次处于不同的状态 CPU的忙碌状况不同 内存的剩余多少不同 等等 所以每次代码的运行 计算机不可能处于完全一样的环境中

  在下面的图中 显示了两个task之间是如何发生竞争的 当两个task启动了之后(虽然说是并行运算 但是不管这样 两个的task的执行时间不可能完全一样 也就是说 不可能恰好就是同时开始执行的 起码在开始执行的时间上是有一点点的差异的)

   .    首先Task 读取到当前的balance的值为

   .    然后 task 运行了 并且也读取到当前的balance值为

   .    两个task都把balance的值加

   .    Task 把balance的值加 后 把新的值保存到了balance中

   .    Task 也把新的保存到了balance中

  所以 结果就是 虽然两个task 都为balance加 但是balance的值还是

  通过这个例子 相信大家应该清楚 为什么上面的 个task执行 而执行后的结果不是 了

   .  解决方案提出

  数据竞争就好比一个生日party 其中 每一个task都是参加party的人 当生日蛋糕出来之后 每个人都兴奋了 如果此时 所有的人都一起冲过去拿属于他们自己的那块蛋糕 此时party就一团糟了 没有如何顺序

  在之前的图示例讲解中 balance那个属性就好比蛋糕 因为task task 都要得到它 然后进行运算 当我们来让多个task共享一个数据时就可能出现问题 下面列出了四种解决方案

   .    顺序执行 也就是让第一个task执行完成之后 再执行第二个

   .    数据不变 我们让task不能修改数据

   .    隔离 我们不共享数据 让每个task都有一份自己的数据拷贝

   .    同步 通过调整task的执行 有序的执行task

  注意 同步和以前多线程中的同步 或者数据库操作时的同步概念不一样

   顺序的执行的解决方案

  顺序的执行解决了通过每次只有一个task访问共享数据的方式解决了数据竞争的问题 其实在本质上 这种解决方案又回到了之前的单线程编程模型 如果拿之前的party分蛋糕的例子 那么现在就是一次只能允许一个人去拿蛋糕

   数据不变解决方案

  数据不变的解决方案就是通过让数据不能被修改的方式来解决共享数据竞争 如果拿之前的蛋糕为例子 那么此时的情况就是 现在蛋糕只能看 不能吃

  在C#中 可以同关键字 readonly 和 const来声明一个字段不能被修改

  public const int AccountNumber= ;

  被声明为const的字段只能通过类型来访问 如 上面的AccountNumber是在Blank类中声明的 那么访问的方式就是Blank AccountNumber

  readonly的字段可以在实例的构造函数中修改

  如下代码

  using System;

  class ImmutableBankAccount

  

  public const int AccountNumber = ;

  public readonly int Balance;

  public ImmutableBankAccount(int InitialBalance)

  

  Balance = InitialBalance;

  

  public ImmutableBankAccount()

            Balance = ;

  

  

  class App

  

  static void Main(string[] args)

  

  // create a bank account with the default balance

  ImmutableBankAccount bankAccount = new ImmutableBankAccount();

  Console WriteLine( Account Number: Account Balance:

  ImmutableBankAccount AccountNumber bankAccount Balance);

  // create a bank account with a starting balance

  ImmutableBankAccount bankAccount = new ImmutableBankAccount( );

  Console WriteLine( Account Number: Account Balance:

  ImmutableBankAccount AccountNumber bankAccount Balance);

  // wait for input before exiting

  Console WriteLine( Press enter to finish );

  Console ReadLine();

  

cha138/Article/program/ASP/201311/21756

相关参考

知识大全 ASP.NET数据库编程之处理文件访问许可

ASP.NET数据库编程之处理文件访问许可  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!一个MDB

知识大全 ASP.NET数据库编程快速入门之技术慨述

ASP.NET数据库编程快速入门之技术慨述  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  大约有

知识大全 并行编程

.NET4特性聚焦:并行编程  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  用语言运行时(Com

知识大全 .NET 4.0函数式编程与协调数据结构

.NET4.0函数式编程与协调数据结构  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  协调数据结

知识大全 ADO.NET的并行控制与数据存取冲突侦测

ADO.NET的并行控制与数据存取冲突侦测  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 VB.Net编程入门之Hello World(4)

VB.Net编程入门之HelloWorld(4)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 asp.net编程程序优化要注意的问题

  一SqlDataRead和Dataset的选择  Sqldataread优点读取数据非常快如果对返回的数据不需做大量处理的情况下建议使用SqlDataReader其性能要比datset好很多缺点直

分布式数据库系统有哪些主要特性?

  分布式数据库系统有以下主要特性  (1)数据独立性;  (2)自治性与共享性;  (3)冗余数据的全局控制;  (4)并行性、一致性和可恢复性;  (5)查询优化特性。

分布式数据库系统有哪些主要特性?

  分布式数据库系统有以下主要特性  (1)数据独立性;  (2)自治性与共享性;  (3)冗余数据的全局控制;  (4)并行性、一致性和可恢复性;  (5)查询优化特性。

知识大全 漫谈.Net PetShop和Duwamish ADO.NET数据库编程

漫谈.NetPetShop和DuwamishADO.NET数据库编程  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快