成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

.NET 4并行編程之共享數(shù)據(jù)問(wèn)題和解決概述

開(kāi)發(fā) 后端
本文介紹的是.NET 4并行編程中應(yīng)該會(huì)遇到的一些問(wèn)題,包括共享數(shù)據(jù)之間的競(jìng)爭(zhēng),以及數(shù)據(jù)不變的解決方案。

之前的文章介紹了了并行編程的一些基礎(chǔ)的知識(shí),從本篇開(kāi)始,將會(huì)講述并行編程中實(shí)際遇到一些問(wèn)題,接下來(lái)的幾篇將會(huì)講述數(shù)據(jù)共享問(wèn)題。

[[12166]]498)this.style.width=498;">

本篇的議題如下:      

1.數(shù)據(jù)競(jìng)爭(zhēng)

2.解決方案提出

3.順序的執(zhí)行解決方案

4.數(shù)據(jù)不變解決方案

在開(kāi)始之前,首先,我們來(lái)看一個(gè)很有趣的例子:

  1. class BankAccount  
  2. {  
  3.     public int Balance  
  4.     {  
  5.         get;  
  6.         set;  
  7.     }  
  8. }  
  9. class App  
  10. {  
  11.     static void Main(string[] args)  
  12.     {  
  13.         // create the bank account instance  
  14.         BankAccount account = new BankAccount();  
  15.         // create an array of tasks  
  16.         Task[] tasks = new Task[10];  
  17.         for (int i = 0; i < 10; i++)  
  18.         {  
  19.             // create a new task  
  20.             tasks[i] = new Task(() =>  
  21.             {  
  22.                 // enter a loop for 1000 balance updates  
  23.                 for (int j = 0; j < 1000; j++)  
  24.                 {  
  25.                     // update the balance  
  26.                     account.Balance = account.Balance + 1;  
  27.                 }  
  28.             });  
  29.             // start the new task  
  30.             tasks[i].Start();  
  31.         }  
  32.  
  33.         // wait for all of the tasks to complete  
  34.         Task.WaitAll(tasks);  
  35.  
  36.         // write out the counter value  
  37.         Console.WriteLine("Expected value {0}, Counter value: {1}",  
  38.         10000, account.Balance);  
  39.  
  40.         // wait for input before exiting  
  41.         Console.WriteLine("Press enter to finish");  
  42.         Console.ReadLine();  
  43.     }  

10個(gè)task,每個(gè)task都是把BankAccount.Balance自增1000次。之后代碼就等到10個(gè)task執(zhí)行完畢,然后打印出Balance的值。大家猜想一下,上次的代碼執(zhí)行完成之后,打印出來(lái)的Balance的結(jié)果是多少?

J結(jié)果確實(shí)和大家猜想的一樣:結(jié)果不等于10000。每次執(zhí)行一次上面的代碼,都會(huì)得到不同的結(jié)果,而且這些結(jié)果值都在10000左右,如果運(yùn)氣好,可能看到有那么一兩次結(jié)果為10000.為什么會(huì)這樣?

下面就是本篇和接下來(lái)的幾篇文章要講述的內(nèi)容。

1.數(shù)據(jù)競(jìng)爭(zhēng)

如果大家對(duì)多線程編程比較熟悉,就知道上面情況的產(chǎn)生是因?yàn)?“共享數(shù)據(jù)競(jìng)爭(zhēng)”導(dǎo)致的(對(duì)多線程不熟悉不清楚的朋友也不用擔(dān)心)。當(dāng)有兩個(gè)或者更多的task在運(yùn)行并且操作同一個(gè)共享公共數(shù)據(jù)的時(shí)候,就存在潛在的競(jìng)爭(zhēng)。如果不合理的處理競(jìng)爭(zhēng)問(wèn)題,就會(huì)出現(xiàn)上面意想不到的情況。

下面就來(lái)分析一下:上面代碼的情況是怎么產(chǎn)生的。

當(dāng)在把a(bǔ)ccount對(duì)象的Balance進(jìn)行自增的時(shí)候,一般執(zhí)行下面的三個(gè)步驟:

  1. 讀取現(xiàn)在account對(duì)象的Balance屬性的值。
  2. 計(jì)算,創(chuàng)建一個(gè)臨時(shí)的新變量,并且把Balance屬性的值賦值給新的變量,而且把新變量的值增加1
  3. 把新變量的值再次賦給account的Balance屬性

在理論上面,上面的三個(gè)步驟是代碼的執(zhí)行步驟,但是實(shí)際中,由于編譯器,.NET 運(yùn)行時(shí)對(duì)自增操作的優(yōu)化操作,和操作系統(tǒng)等的因素,在執(zhí)行上面代碼的時(shí)候,并不一定是按照我們?cè)O(shè)想的那樣運(yùn)行的,但是為了分析的方便,我們還是假設(shè)代碼是按照上面的三個(gè)步驟運(yùn)行的。

之前的代碼每次執(zhí)行一次,執(zhí)行代碼的計(jì)算機(jī)就每次處于不同的狀態(tài):CPU的忙碌狀況不同,內(nèi)存的剩余多少不同,等等,所以每次代碼的運(yùn)行,計(jì)算機(jī)不可能處于完全一樣的環(huán)境中。

在下面的圖中,顯示了兩個(gè)task之間是如何發(fā)生競(jìng)爭(zhēng)的。當(dāng)兩個(gè)task啟動(dòng)了之后(雖然說(shuō)是并行運(yùn)算,但是不管這樣,兩個(gè)的task的執(zhí)行時(shí)間不可能完全一樣,也就是說(shuō),不可能恰好就是同時(shí)開(kāi)始執(zhí)行的,起碼在開(kāi)始執(zhí)行的時(shí)間上是有一點(diǎn)點(diǎn)的差異的)。

架構(gòu)差異

1.    首先Task1讀取到當(dāng)前的balance的值為0。

2.    然后,task2運(yùn)行了,并且也讀取到當(dāng)前的balance值為0。

3.    兩個(gè)task都把balance的值加1

4.    Task1把balance的值加1后,把新的值保存到了balance中

5.    Task2 也把新的保存到了balance中

所以,結(jié)果就是:雖然兩個(gè)task 都為balance加1,但是balance的值還是1。

通過(guò)這個(gè)例子,相信大家應(yīng)該清楚,為什么上面的10個(gè)task執(zhí)行1000,而執(zhí)行后的結(jié)果不是10000了。 

2.  解決方案提出

數(shù)據(jù)競(jìng)爭(zhēng)就好比一個(gè)生日party。其中,每一個(gè)task都是參加party的人,當(dāng)生日蛋糕出來(lái)之后,每個(gè)人都興奮了。如果此時(shí),所有的人都一起沖過(guò)去拿屬于他們自己的那塊蛋糕,此時(shí)party就一團(tuán)糟了,沒(méi)有如何順序。

在之前的圖示例講解中,balance那個(gè)屬性就好比蛋糕,因?yàn)閠ask1,task2都要得到它,然后進(jìn)行運(yùn)算。當(dāng)我們來(lái)讓多個(gè)task共享一個(gè)數(shù)據(jù)時(shí)就可能出現(xiàn)問(wèn)題。下面列出了四種解決方案:

1.    順序執(zhí)行:也就是讓第一個(gè)task執(zhí)行完成之后,再執(zhí)行第二個(gè)。

2.    數(shù)據(jù)不變:我們讓task不能修改數(shù)據(jù)。

3.    隔離:我們不共享數(shù)據(jù),讓每個(gè)task都有一份自己的數(shù)據(jù)拷貝。

4.    同步:通過(guò)調(diào)整task的執(zhí)行,有序的執(zhí)行task。

注意:同步和以前多線程中的同步,或者數(shù)據(jù)庫(kù)操作時(shí)的同步概念不一樣

3.順序的執(zhí)行的解決方案

順序的執(zhí)行解決了通過(guò)每次只有一個(gè)task訪問(wèn)共享數(shù)據(jù)的方式解決了數(shù)據(jù)競(jìng)爭(zhēng)的問(wèn)題,其實(shí)在本質(zhì)上,這種解決方案又回到了之前的單線程編程模型。如果拿之前的party分蛋糕的例子,那么現(xiàn)在就是一次只能允許一個(gè)人去拿蛋糕。

4.數(shù)據(jù)不變解決方案

數(shù)據(jù)不變的解決方案就是通過(guò)讓數(shù)據(jù)不能被修改的方式來(lái)解決共享數(shù)據(jù)競(jìng)爭(zhēng)。如果拿之前的蛋糕為例子,那么此時(shí)的情況就是:現(xiàn)在蛋糕只能看,不能吃。

在C#中,可以同關(guān)鍵字 readonly 和 const來(lái)聲明一個(gè)字段不能被修改:

public const int AccountNumber=123456;

被聲明為const的字段只能通過(guò)類型來(lái)訪問(wèn):如,上面的AccountNumber是在Blank類中聲明的,那么訪問(wèn)的方式就是Blank. AccountNumber

readonly的字段可以在實(shí)例的構(gòu)造函數(shù)中修改。

如下代碼:

  1. using System;  
  2.  
  3. class ImmutableBankAccount  
  4. {  
  5.     public const int AccountNumber = 123456;  
  6.     public readonly int Balance;  
  7.     public ImmutableBankAccount(int InitialBalance)  
  8.     {  
  9.         Balance = InitialBalance;  
  10.     }  
  11.     public ImmutableBankAccount()  
  12.     {  
  13.         Balance = 0;  
  14.     }  
  15. }  
  16.  
  17. class App  
  18. {  
  19.     static void Main(string[] args)  
  20.     {  
  21.         // create a bank account with the default balance  
  22.         ImmutableBankAccount bankAccount1 = new ImmutableBankAccount();  
  23.         Console.WriteLine("Account Number: {0}, Account Balance: {1}",  
  24.  
  25.         ImmutableBankAccount.AccountNumber, bankAccount1.Balance);  
  26.  
  27.         // create a bank account with a starting balance  
  28.         ImmutableBankAccount bankAccount2 = new ImmutableBankAccount(200);  
  29.         Console.WriteLine("Account Number: {0}, Account Balance: {1}",  
  30.         ImmutableBankAccount.AccountNumber, bankAccount2.Balance);  
  31.  
  32.         // wait for input before exiting  
  33.         Console.WriteLine("Press enter to finish");  
  34.         Console.ReadLine();  
  35.     }  

數(shù)據(jù)不變的解決方案不是很常用,因?yàn)樗鼘?duì)數(shù)據(jù)限制太大了。

原文標(biāo)題:.NET 并行(多核)編程系列之七 共享數(shù)據(jù)問(wèn)題和解決概述 

鏈接:http://www.cnblogs.com/yanyangtian/archive/2010/06/24/1764098.html

【編輯推薦】

  1. 微軟發(fā)布新版Windows 7及.NET 4軟件開(kāi)發(fā)工具包
  2. 詳解.NET 4.0并行計(jì)算支持歷史
  3. 詳讀.NET 4.0環(huán)境配置
  4. 詳解.NET 4.0中異常處理方面的新特性
  5. 三方面詮釋.NET 4.0的新特性
責(zé)任編輯:彭凡 來(lái)源: 博客園
相關(guān)推薦

2010-06-11 09:01:02

.NET 4并行編程

2010-06-02 08:53:51

.NET 4并行編程

2010-06-04 09:11:10

.NET并行編程

2010-06-08 08:41:08

.NET 4并行編程

2010-06-07 08:43:46

.NET 4并行編程

2021-03-05 07:38:52

C++線程編程開(kāi)發(fā)技術(shù)

2009-07-22 17:45:35

ASP.NET教程

2010-06-09 09:18:34

.NET 4并行編程

2020-05-09 22:54:48

物聯(lián)網(wǎng)安全物聯(lián)網(wǎng)IOT

2009-06-29 09:38:50

JSF標(biāo)簽JSF

2011-06-22 10:20:11

QT 鼠標(biāo) 拖放

2020-03-11 09:57:10

數(shù)據(jù)安全網(wǎng)絡(luò)安全網(wǎng)絡(luò)攻擊

2015-10-13 09:18:00

.Net編程教程

2013-07-30 14:00:46

.NET數(shù)據(jù)類型

2011-03-31 16:45:39

Redhat配置nagios

2012-03-09 10:44:11

Java

2018-03-09 16:27:50

數(shù)據(jù)庫(kù)Oracle同步問(wèn)題

2022-03-31 10:25:20

物聯(lián)網(wǎng)工業(yè) 4.0大數(shù)據(jù)分析

2023-10-16 16:08:42

工業(yè) 4.0物聯(lián)網(wǎng)邊緣計(jì)算

2024-10-10 15:32:51

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 91免费视频 | 亚洲视频二区 | 久草热在线| 亚洲激情专区 | 成人精品国产 | 中文字幕在线免费观看 | 欧美成人一区二区三区 | 久久se精品一区精品二区 | 91精品国产综合久久久久久丝袜 | 国产精品高 | 国产日产欧产精品精品推荐蛮挑 | 欧洲性生活视频 | 91极品尤物在线播放国产 | 日本成人久久 | 国产美女一区二区 | 欧美a级成人淫片免费看 | 欧美成人a∨高清免费观看 老司机午夜性大片 | 青青草社区 | 精品国产一区二区三区性色 | 天天欧美 | 国产精品久久久久国产a级 欧美日韩国产免费 | 麻豆国产一区二区三区四区 | 九九亚洲精品 | 日韩视频成人 | 亚洲成人国产精品 | 99久久精品免费看国产小宝寻花 | 综合一区 | 亚洲免费在线观看 | 一区二区三区网站 | 91精品国产综合久久精品 | 成人黄色电影在线播放 | www312aⅴ欧美在线看 | 午夜一级大片 | 亚洲国产精选 | 先锋av资源在线 | 成人免费在线观看视频 | 一区在线免费视频 | 欧美日韩在线观看一区 | 国产成人精品网站 | 精品一区二区电影 | 成人在线视频免费看 |