日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
.NET4并行編程之共享數(shù)據(jù)問題和解決概述

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

作為一家“創(chuàng)意+整合+營銷”的成都網(wǎng)站建設(shè)機構(gòu),我們在業(yè)內(nèi)良好的客戶口碑。創(chuàng)新互聯(lián)提供從前期的網(wǎng)站品牌分析策劃、網(wǎng)站設(shè)計、做網(wǎng)站、成都網(wǎng)站設(shè)計、創(chuàng)意表現(xiàn)、網(wǎng)頁制作、系統(tǒng)開發(fā)以及后續(xù)網(wǎng)站營銷運營等一系列服務(wù),幫助企業(yè)打造創(chuàng)新的互聯(lián)網(wǎng)品牌經(jīng)營模式與有效的網(wǎng)絡(luò)營銷方法,創(chuàng)造更大的價值。

本篇的議題如下:

1.數(shù)據(jù)競爭

2.解決方案提出

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

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

在開始之前,首先,我們來看一個很有趣的例子:

 
 
 
 
  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.         // wait for all of the tasks to complete
  33.         Task.WaitAll(tasks);
  34.         // write out the counter value
  35.         Console.WriteLine("Expected value {0}, Counter value: {1}",
  36.         10000, account.Balance);
  37.         // wait for input before exiting
  38.         Console.WriteLine("Press enter to finish");
  39.         Console.ReadLine();
  40.     }
  41. }

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

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

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

1.數(shù)據(jù)競爭

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

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

當在把account對象的Balance進行自增的時候,一般執(zhí)行下面的三個步驟:

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

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

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

在下面的圖中,顯示了兩個task之間是如何發(fā)生競爭的。當兩個task啟動了之后(雖然說是并行運算,但是不管這樣,兩個的task的執(zhí)行時間不可能完全一樣,也就是說,不可能恰好就是同時開始執(zhí)行的,起碼在開始執(zhí)行的時間上是有一點點的差異的)。

1.    首先Task1讀取到當前的balance的值為0。

2.    然后,task2運行了,并且也讀取到當前的balance值為0。

3.    兩個task都把balance的值加1

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

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

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

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

2.  解決方案提出

數(shù)據(jù)競爭就好比一個生日party。其中,每一個task都是參加party的人,當生日蛋糕出來之后,每個人都興奮了。如果此時,所有的人都一起沖過去拿屬于他們自己的那塊蛋糕,此時party就一團糟了,沒有如何順序。

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

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

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

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

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

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

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

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

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

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

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

public const int AccountNumber=123456;

被聲明為const的字段只能通過類型來訪問:如,上面的AccountNumber是在Blank類中聲明的,那么訪問的方式就是Blank. AccountNumber

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

如下代碼:

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

數(shù)據(jù)不變的解決方案不是很常用,因為它對數(shù)據(jù)限制太大了。

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


網(wǎng)頁名稱:.NET4并行編程之共享數(shù)據(jù)問題和解決概述
URL鏈接:http://www.dlmjj.cn/article/cojjode.html