Simple simulation of Channel and goroutine mechanisms in the Google Go language using C #

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Some time ago tried a little Google Go language, feel a lot of features are good. The Go language is designed to combine the advantages of traditional compiled static language and interpreted dynamic language to find a balance. This creates a language that is fast (compiled and executed) and easy to program (dynamic languages tend to be simple and fast syntax). At the same time, the Go language is also rich in features to support concurrent programming, which is a very important and powerful feature in today's multicore environment.

The concurrency features of Go language mainly include Goroutine, channel, etc.

Goroutine-can be roughly understood as a lightweight thread (or micro-threading), which is a "function that is allocated in the same address space and can be executed in parallel". At the same time, it is lightweight and does not need to allocate a separate stack space as assigned threads. So theoretically, we can easily allocate many goroutine, let them execute concurrently, and its overhead is much smaller than multithreaded programs, so that the program can support a larger concurrency.

Channel-as the name implies, is the passage. The purpose of the channel is to pass data. On one channel we can perform the send and accept (receive) operations of the data. For a non-buffered channel, when the Receive method executes, it determines whether there is a value on the channel, and if not, waits (blocks) until a value is reached. Similarly, when there is a value on the channel, and not yet accepted by a Receiver, the Send method also blocks until the channel becomes empty. In this way, a simple mechanism ensures that send and receive are always executed at different times, and only after send can receive. This avoids the common problem of data sharing in multithreaded programming. As the Go language document says in a word:

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

Do not communicate through shared memory, but rather through communication to share memory.

In regular multithreaded programming, we always define some class variables, and if they are potentially accessed by multiple threads at the same time, they need to be locked. This brings a certain amount of programming complexity, and if the code writes a slight bug, it causes a read/write to the wrong value.

and through channel communication, we get a clearer way of communicating. Two threads (or goroutine) to read and write the same data, create a channel where both sides can set values or values by performing send/receive operations on the channel, which is relatively less prone to error.

To better understand this principle, I tried to implement similar functionality in C #.

I did not implement micro-threading, as opposed to goroutine, because it requires a more complex scheduling mechanism (which is intended to be further studied in the next step). We can use Thread briefly to simulate it.

And the Channel, then use Semaphone control synchronous send/receive can be.

Let us first implement a simple Channel, as the thought above has said:

<summary>///first implement simple unbuffered channel.///</summary>///<typeparam name= "T" ></typeparam> public class Channel<t>{t _value;//start cannot receive.semaphore _canreceive = new Semaphore (0, 1);//Start without value, you can Sendsemapho Re _cansend = new Semaphore (1, 1);p ublic T Receive () {//wait for a value _canreceive.waitone (); T value = _value;//notification can send a new value of _cansend.release (); return value;} public void Send (T value) {///if it is a non-buffered case, it is blocked and needs to wait for an existing value to be accepted by a Receiver,//To send a new value, not to send_cansend.waitone continuously (); _value = value;//notification can receive _canreceive.release ();}}

The following rough simulation implements the Goroutine syntax:

public static class golang{///<summary>///a simple thread to simulate the goroutine. Because the channel communication is used,///The data sharing/synchronization problem between threads is not required///</ summary>///<param name= "action" ></param>public static void Go (Action action) {new Thread (new ThreadStart (Action)). Start ();}}

With this, we can write a test case to verify it. The following code simply creates a concurrent routine, making an integer send, receive operation to verify that the values are correctly sent and accepted:

<summary>///test multiple sender Receiver simultaneously send/receive messages on a channel//</summary>private static void Test1 () {var c h = new channel<int> ();//Start Multiple Sendergolang.go (() =>{var id = thread.currentthread.managedthreadid;for (var i = 0 ; I < 7; i++) {Thread.Sleep (New Random ((int) DateTime.Now.Ticks). Next (3000)); Console.WriteLine ("Thread {0} send value: {1}", ID, i); Ch. Send (i);}}); Golang.go (() =>{var id = thread.currentthread.managedthreadid;for (var i = 7; I < i++) {Thread.Sleep (New Random ( int) DateTime.Now.Ticks). Next (3000)); Console.WriteLine ("Thread {0} send value: {1}", ID, i); Ch. Send (i);}}); /Start multiple Receivergolang.go (() =>{var id = thread.currentthread.managedthreadid;for (var i = 0; i < 5; i++) {//CONSOLE.W Riteline ("thread {0} blocked", id); var value = ch. Receive (); Console.WriteLine ("Thread {0} obtained value: {1}", id, value);}); Golang.go (() =>{var id = thread.currentthread.managedthreadid;for (var i = 0; i < 5; i++) {//console.writeline ("thread {0} Block ", id); var value = ch. Receive (); Console.WriteLine ("Thread {0}" gets the value: {1} ", id, value);}); Golang.go (() =>{var id = thread.currentthread.managedthreadid;for (var i = 0; i < 5; i++) {//console.writeline ("thread {0} Block ", id); var value = ch. Receive (); Console.WriteLine ("Thread {0} obtained value: {1}", id, value);});}

Try to implement one of the examples in the Go language document-The Sieve method for prime numbers:

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

public class Primenumbers{public void Main () {var primes = Sieve ();//test: Print the first 100 primes for (var i = 0; i <; i++) {Console. WriteLine (primes. Receive ());}} <summary>///Sieve method for primes///</summary>///<returns></returns>Channel<int> Sieve () {var @ out = new channel<int> (); Golang.go (() =>{var ch = Generate (); for (;;) The first value in the {///current sequence is always a prime number var prime = ch. Receive ();//sends it to the trailing @out of the output sequence. Send (prime);//Use this prime number to filter the list, in the next loop, you can guarantee that at least the first digit is prime ch = Filter (ch, prime);}); return @out;} <summary>///produces an infinite sequence of natural numbers starting from 2, which is the original sequence///Its starting element 2 is a prime number. </summary>///<returns></returns>Channel<int> Generate () {var ch = new Channel<int> ( ); Golang.go (() =>{for (var i = 2;; i++) {ch. Send (i);}}); return ch;} <summary>///reads the values from the input Channel One at a time, sending those that cannot be divisible by the prime//to the output channel (that is, once the @in sequence is screened with prime)//</summary>c Hannel<int> Filter (channel<int> @in, int prime) {var @out = new channel<int> (); Golang.go (() =>{for (;;) {VAR i = @in. Receive (); if (i% prime! = 0) {@out. Send (i);}}); return @out;}}

Here is the Main method for the entire test project:

Class program{static void Main (string[] args) {Test1 (); new Primenumbers (). Main (); Console.ReadLine ();}}

Because the code has been commented in detail, not much to explain. As you can see, using the concept of Channel (as if it had something to do with reactive programming?) , we can build multi-threaded or concurrent applications more clearly.

Learning other languages is not about learning a particular grammar, but learning a thought.

Author: mu Wild fox @ Blog Park

Reprint please indicate the source.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.