日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁(yè)編程開發(fā)C#.NET → 用 C# 實(shí)現(xiàn)Google Go 語(yǔ)言中的Channel 和 goroutine 機(jī)制

      用 C# 實(shí)現(xiàn)Google Go 語(yǔ)言中的Channel 和 goroutine 機(jī)制

      相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:本站整理時(shí)間:2010/8/25 19:35:49字體大。A-A+

      作者:佚名點(diǎn)擊:110次評(píng)論:1次標(biāo)簽: Google Channel

      3D建模(Google SketchUp)8.0.11752 官方免費(fèi)版
      • 類型:3D 制作大。35.7M語(yǔ)言:英文 評(píng)分:4.1
      • 標(biāo)簽:
      立即下載

      前段時(shí)間嘗試了一點(diǎn) Google 的 Go 語(yǔ)言,感覺其很多特性還是不錯(cuò)的。Go 語(yǔ)言旨在結(jié)合傳統(tǒng)編譯型的靜態(tài)語(yǔ)言和解釋型的動(dòng)態(tài)語(yǔ)言的優(yōu)點(diǎn),在其中找到一個(gè)平衡。從而打造一個(gè)既快速(編譯執(zhí)行),又方便編程的語(yǔ)言(動(dòng)態(tài)語(yǔ)言往往語(yǔ)法簡(jiǎn)單快捷)。同時(shí),Go 語(yǔ)言還具備豐富的特性以支持并發(fā)編程,這在現(xiàn)在多核非常普及的情況下,是很重要和強(qiáng)大的一個(gè)功能。

      Go 語(yǔ)言的并發(fā)特性主要有 goroutine, channel 等。goroutine - 可以大致理解為一種輕量級(jí)的線程(或微線程),它是一種“分配在同一個(gè)地址空間內(nèi)的,能夠并行執(zhí)行的函數(shù)”。同時(shí),它是輕量級(jí)的,不需要像分配線程那樣分配獨(dú)立的?臻g。所以理論上講,我們可以很容易的分配很多個(gè) goroutine, 讓它們并發(fā)執(zhí)行,而其開銷則比多線程程序要小得多,從而可以讓程序支持比較大的并發(fā)性。

      channel - 顧名思義,就是通道。通道的目的是用來(lái)傳遞數(shù)據(jù)。在一個(gè)通道上我們可以執(zhí)行數(shù)據(jù)的發(fā)送(Send)和接受(Receive)操作。對(duì)于非緩沖的 channel 而言,Receive 方法執(zhí)行時(shí),會(huì)判斷該通道上是否有值,如果沒有就會(huì)等待(阻塞),直到有一個(gè)值為止。同樣,在 channel 上有值,而尚未被一個(gè) Receiver 接受的時(shí)候,Send 方法也會(huì)阻塞,直到 Channel 變空。這樣,通過(guò)一個(gè)簡(jiǎn)單的機(jī)制就可以保證 Send 和 Receive 總是在不同的時(shí)間執(zhí)行的,而且只有 Send 之后才能 Receive. 這樣就避免了常規(guī)的多線程編程中數(shù)據(jù)共享的問題。正如 Go 語(yǔ)言的文檔一句話所說(shuō):

      Do not communicate by sharing memory; instead, share memory by communicating.

      不要通過(guò)共享內(nèi)存來(lái)溝通;而是通過(guò)溝通來(lái)共享內(nèi)存。

      在常規(guī)的多線程編程里,我們總是定義好一些類變量,如果這些變量有可能被多個(gè)線程同時(shí)訪問,那么就需要加鎖。這樣帶來(lái)了一定的編程復(fù)雜性,如果代碼寫的稍有bug,則會(huì)導(dǎo)致讀/寫到錯(cuò)誤的值。

      而通過(guò) channel 來(lái)溝通,我們得到了一個(gè)更為清晰的溝通方式。兩個(gè)線程(或者 goroutine)要讀寫相同的數(shù)據(jù),則創(chuàng)建一個(gè)通道,雙方通過(guò)對(duì)這個(gè)通道執(zhí)行 Send / Receive 的操作來(lái)設(shè)值或取值即可,相對(duì)而言,比較不容易出錯(cuò)。

      為了更好的理解這個(gè)原理,我嘗試了在 C# 中實(shí)現(xiàn)類似的功能。

      相對(duì)于 goroutine, 我沒有去實(shí)現(xiàn)微線程,因?yàn)檫@需要更復(fù)雜的調(diào)度機(jī)制(打算接下來(lái)進(jìn)一步研究這方面)。我們可以暫時(shí)利用 Thread 來(lái)簡(jiǎn)單的模擬之。

      而 Channel, 則用 Semaphone 控制同步的 Send / Receive 就可以了。

      首先讓我們來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Channel,思想上面已經(jīng)說(shuō)過(guò)了:

      view sourceprint?01 /// <summary>

      02 /// 先實(shí)現(xiàn)簡(jiǎn)單的沒有緩沖的 Channel.

      03 /// </summary>

      04 /// <typeparam name="T"></typeparam>

      05 public class Channel<T>

      06 {

      07 T _value;

      08

      09 // 開始不能 Receive.

      10 Semaphore _canReceive = new Semaphore(0, 1);

      11

      12 // 開始沒有值,可以 Send

      13 Semaphore _canSend = new Semaphore(1, 1);

      14

      15 public T Receive()

      16 {

      17 // 等待有值

      18 _canReceive.WaitOne();

      19

      20 T value = _value;

      21

      22 // 通知可以發(fā)送新的值了

      23 _canSend.Release();

      24

      25 return value;

      26 }

      27

      28 public void Send(T value)

      29 {

      30 // 如果是非緩沖的情況,則為阻塞式的,需要等待已有的值被一個(gè) Receiver 接受完,

      31 // 才能發(fā)送新值,不能連續(xù) Send

      32 _canSend.WaitOne();

      33 _value = value;

      34

      35 // 通知可以接收了

      36 _canReceive.Release();

      37 }

      38 }

      接下來(lái)粗略的模擬實(shí)現(xiàn) goroutine 的語(yǔ)法:

      view sourceprint?01 public static class GoLang

      02 {

      03 /// <summary>

      04 /// 先簡(jiǎn)單的用線程來(lái)模擬 goroutine. 因?yàn)槭褂?channel 通信,所以

      05 /// 不需考慮線程之間的數(shù)據(jù)共享/同步問題

      06 /// </summary>

      07 /// <param name="action"></param>

      08 public static void go(Action action)

      09 {

      10 new Thread(new ThreadStart(action)).Start();

      11 }

      12

      13 }

      有了這些,我們可以寫一個(gè) test case 來(lái)驗(yàn)證了。下面的代碼簡(jiǎn)單的創(chuàng)建一個(gè)并發(fā)的 routine,分別做整數(shù)的 send, receive 操作,以驗(yàn)證是否能正確的發(fā)送和接受值:

      view sourceprint?01 /// <summary>

      02 /// 測(cè)試多個(gè) Sender 多個(gè) Receiver 同時(shí)在一個(gè) channel 上發(fā)送/接受消息

      03 /// </summary>

      04 private static void Test1()

      05 {

      06 var ch = new Channel<int>();

      07

      08 // 啟動(dòng)多個(gè) Sender

      09 GoLang.go(() =>

      10 {

      11 var id = Thread.CurrentThread.ManagedThreadId;

      12 for (var i = 0; i < 7; i++)

      13 {

      14 Thread.Sleep(new Random((int)DateTime.Now.Ticks).Next(3000));

      15 Console.WriteLine("線程{0}發(fā)送值: {1}", id, i);

      16 ch.Send(i);

      17 }

      18 });

      19

      20 GoLang.go(() =>

      21 {

      22 var id = Thread.CurrentThread.ManagedThreadId;

      23 for (var i = 7; i < 15; i++)

      24 {

      25 Thread.Sleep(new Random((int)DateTime.Now.Ticks).Next(3000));

      26 Console.WriteLine("線程{0}發(fā)送值: {1}", id, i);

      27 ch.Send(i);

      28 }

      29 });

      30

      31 // 啟動(dòng)多個(gè) Receiver

      32 GoLang.go(() =>

      33 {

      34 var id = Thread.CurrentThread.ManagedThreadId;

      35 for (var i = 0; i < 5; i++)

      36 {

      37 //Console.WriteLine("線程{0}阻塞", id);

      38 var value = ch.Receive();

      39 Console.WriteLine("線程{0}獲得值: {1}", id, value);

      40 }

      41 });

      42

      43 GoLang.go(() =>

      44 {

      45 var id = Thread.CurrentThread.ManagedThreadId;

      46 for (var i = 0; i < 5; i++)

      47 {

      48 //Console.WriteLine("線程{0}阻塞", id);

      49 var value = ch.Receive();

      50 Console.WriteLine("線程{0}獲得值: {1}", id, value);

      51 }

      52 });

      53

      54 GoLang.go(() =>

      55 {

      56 var id = Thread.CurrentThread.ManagedThreadId;

      57 for (var i = 0; i < 5; i++)

      58 {

      59 //Console.WriteLine("線程{0}阻塞", id);

      60 var value = ch.Receive();

      61 Console.WriteLine("線程{0}獲得值: {1}", id, value);

      62 }

      63 });

      64 }

      再嘗試實(shí)現(xiàn)一下 Go 語(yǔ)言文檔里舉出的一個(gè)例子 - 篩法求素?cái)?shù):

      (見:http://golang.org/doc/go_tutorial.html, Prime numbers)

      view sourceprint?01 public class PrimeNumbers

      02 {

      03 public void Main()

      04 {

      05 var primes = Sieve();

      06

      07 // 測(cè)試:打印前100個(gè)素?cái)?shù)

      08 for (var i = 0; i < 100; i++)

      09 {

      10 Console.WriteLine(primes.Receive());

      11 }

      12 }

      13

      14 /// <summary>

      15 /// 篩法求素?cái)?shù)

      16 /// </summary>

      17 /// <returns></returns>

      18 Channel<int> Sieve()

      19 {

      20 var @out = new Channel<int>();

      21 GoLang.go(() =>

      22 {

      23 var ch = Generate();

      24 for (; ; )

      25 {

      26 // 當(dāng)前序列中的第一個(gè)值總是素?cái)?shù)

      27 var prime = ch.Receive();

      28

      29 // 將其發(fā)送到輸出序列的尾部

      30 @out.Send(prime);

      31

      32 // 用這個(gè)素?cái)?shù)對(duì)列表進(jìn)行過(guò)濾,在進(jìn)入下一次循環(huán),可以保證至少第一個(gè)數(shù)是素?cái)?shù)

      33 ch = Filter(ch, prime);

      34 }

      35 });

      36 return @out;

      37 }

      38

      39 /// <summary>

      40 /// 產(chǎn)生從2開始的自然數(shù)的無(wú)窮序列,這是原始數(shù)列

      41 /// 其開始元素 2 是一個(gè)素?cái)?shù)。

      42 /// </summary>

      43 /// <returns></returns>

      44 Channel<int> Generate()

      45 {

      46 var ch = new Channel<int>();

      47 GoLang.go(() =>

      48 {

      49 for (var i = 2; ; i++)

      50 {

      51 ch.Send(i);

      52 }

      53 });

      54 return ch;

      55 }

      56

      57 /// <summary>

      58 /// 從輸入 channel 里逐個(gè)讀取值,將不能被 prime 整除

      59 /// 的那些發(fā)送到輸出 channel (即用 prime 對(duì) @in 序列進(jìn)行一次篩選)

      60 /// </summary>

      61 Channel<int> Filter(Channel<int> @in, int prime)

      62 {

      63 var @out = new Channel<int>();

      64 GoLang.go(() =>

      65 {

      66 for (; ; )

      67 {

      68 var i = @in.Receive();

      69 if (i % prime != 0)

      70 {

      71 @out.Send(i);

      72 }

      73 }

      74 });

      75 return @out;

      76 }

      77 }

      下面是整個(gè)測(cè)試工程的 Main 方法:

      view sourceprint?01 class Program

      02 {

      03 static void Main(string[] args)

      04 {

      05 Test1();

      06

      07 new PrimeNumbers().Main();

      08

      09 Console.ReadLine();

      10 }

      11 }

      因?yàn)榇a中已經(jīng)詳細(xì)注釋了,不多做解釋。可以看到,利用 Channel 的概念(好像和 Reactive Programming 有點(diǎn)關(guān)系?),我們可以更清晰的構(gòu)建多線程或者并發(fā)的應(yīng)用程序。

      學(xué)習(xí)其他語(yǔ)言,并不是為了學(xué)習(xí)其特定的語(yǔ)法,而是學(xué)習(xí)一種思想。

        3D建模軟件
        (69)3D建模軟件
        建模軟件是專門針對(duì)于三維立體的建模制圖等相關(guān)的一系列的軟件,建模通俗來(lái)講就是通過(guò)三維制作軟件通過(guò)虛擬三維空間構(gòu)建出具有三維數(shù)據(jù)的模型,這里建模軟件是包含有打印建模軟件動(dòng)畫制作軟件建模相關(guān)教程建模視頻教程建模渲染動(dòng)畫制作教程動(dòng)畫三維動(dòng)畫制作視頻動(dòng)畫制作等相關(guān)的一系列的軟件,這里說(shuō)道制作,動(dòng)畫游戲公司用會(huì)多一點(diǎn),建模操作簡(jiǎn)單,涉及到動(dòng)作和特效的插件很多,自帶的功能也很強(qiáng)大室內(nèi)設(shè)計(jì)一般會(huì)用到多一點(diǎn)。...更多>>

        相關(guān)評(píng)論

        閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過(guò)難過(guò)
        • 5 囧
        • 3 圍觀圍觀
        • 2 無(wú)聊無(wú)聊

        熱門評(píng)論

        最新評(píng)論

        發(fā)表評(píng)論 查看所有評(píng)論(1)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)