Concurrent collections of C # Parallel programming (. Net Framework 4.0)

Source: Internet
Author: User

This article summarizes and debugs some of the code examples in the article for a personal study of the Advanced tutorial on C # parallel programming. Can be used later in the development process.


For parallel tasks, it is closely related to parallel access to some shared resources, data structures. The most common thing to do is to lock up some queues-unlock them, and then perform mutex operations like insertions, deletions, and so on. NETFramework 4.0 provides a number of packaged support parallel operation data containers that can reduce the complexity of parallel programming.


Basic information

. namespaces for parallel collections in NETFramework: System.Collections.Concurrent

Parallel containers:

    • Concurrentqueue
    • Concurrentstack
    • Concurrentbag: An unordered set of data structures that is useful when you don't need to consider order.
    • BlockingCollection: Similar to the classic blocking queue data structure
    • Concurrentdictionary

These collections use a lock-free technique (CAS compare-and-swap and memory barrier Memories Barrier) to some extent, and gain performance gains over mutex locks. In a serial program, however, it is best not to use these collections, which inevitably affect performance.
About CAS:
    • http://www.tuicool.com/articles/zuui6z
    • Http://www.360doc.com/content/11/0914/16/7656248_148221200.shtml
About Memory barriers
    • Http://en.wikipedia.org/wiki/Memory_barrier

Usage and example Concurrentqueue are completely unlocked, but may get stuck in spin and retry operations when CAS face resource contention failures.
    • Enqueue: Inserting elements at the end of a team
    • Trydequeue: Attempt to delete the team header element and return through the out parameter
    • Trypeek: Attempts to return the head element through the out parameter, but does not delete the element.

Examples of programs:
Using system;using system.text;using system.threading.tasks;using system.collections.concurrent;namespace Sample4_1        _concurrent_queue{class Program {internal static concurrentqueue<int> _testqueue;            Class ThreadWork1//producer {public ThreadWork1 () {} public void run ()                {System.Console.WriteLine ("ThreadWork1 run {"); for (int i = 0; i < i++) {System.Console.WriteLine ("ThreadWork1 producer:" + I                    );                _testqueue.enqueue (i);            } System.Console.WriteLine ("ThreadWork1 Run}");  }} class ThreadWork2//consumer {public ThreadWork2 () {} public                void run () {int i = 0;                BOOL Isdequeuue = false;                System.Console.WriteLine ("ThreadWork2 run {");         for (;;)       {Isdequeuue = _testqueue.trydequeue (out i);                    if (Isdequeuue) System.Console.WriteLine ("ThreadWork2 Consumer:" + i * i + "=====");                if (i = =) break;            } System.Console.WriteLine ("ThreadWork2 Run}");            }} static void StartT1 () {ThreadWork1 work1 = new ThreadWork1 ();        Work1.run ();            } static void StartT2 () {THREADWORK2 work2 = new ThreadWork2 ();        Work2.run ();            } static void Main (string[] args) {Task T1 = new Task (() = StartT1 ());            Task t2 = new Task (() = StartT2 ());            _testqueue = new concurrentqueue<int> ();            Console.WriteLine ("Sample 3-1 Main {");            Console.WriteLine ("Main T1 T2 started {"); T1.            Start (); T2.            Start (); Console.WriteLine ("Main T1 T2 started} ");            Console.WriteLine ("Main wait T1 T2 end {");            Task.waitall (t1, T2);            Console.WriteLine ("Main wait T1 T2 End}");            Console.WriteLine ("Sample 3-1 Main}");        Console.readkey (); }    }}



Concurrentstack is completely unlocked, but it may get stuck in a spin and retry operation when the CAs face resource contention failure.

    • Push: Inserts an element into the top of the stack
    • Trypop: Eject element from top of stack and return by out parameter
    • Trypeek: Returns the top element of the stack, but does not eject.

Examples of programs:
Using system;using system.text;using system.threading.tasks;using system.collections.concurrent;namespace Sample4_2        _concurrent_stack{class Program {internal static concurrentstack<int> _teststack;            Class ThreadWork1//producer {public ThreadWork1 () {} public void run ()                {System.Console.WriteLine ("ThreadWork1 run {"); for (int i = 0; i < i++) {System.Console.WriteLine ("ThreadWork1 producer:" + I                    );                _teststack.push (i);            } System.Console.WriteLine ("ThreadWork1 Run}");  }} class ThreadWork2//consumer {public ThreadWork2 () {} public                void run () {int i = 0;                BOOL Isdequeuue = false;                System.Console.WriteLine ("ThreadWork2 run {");            for (;;)    {Isdequeuue = _teststack.trypop (out i);                    if (Isdequeuue) System.Console.WriteLine ("ThreadWork2 Consumer:" + i * i + "=====" + i);                if (i = =) break;            } System.Console.WriteLine ("ThreadWork2 Run}");            }} static void StartT1 () {ThreadWork1 work1 = new ThreadWork1 ();        Work1.run ();            } static void StartT2 () {THREADWORK2 work2 = new ThreadWork2 ();        Work2.run ();            } static void Main (string[] args) {Task T1 = new Task (() = StartT1 ());            Task t2 = new Task (() = StartT2 ());            _teststack = new concurrentstack<int> ();            Console.WriteLine ("Sample 4-1 Main {");            Console.WriteLine ("Main T1 T2 started {"); T1.            Start (); T2.            Start (); Console.WriteLine ("Main t1 T2 started} ");            Console.WriteLine ("Main wait T1 T2 end {");            Task.waitall (t1, T2);            Console.WriteLine ("Main wait T1 T2 End}");            Console.WriteLine ("Sample 4-1 Main}");        Console.readkey (); }    }}

An interesting phenomenon in the test:
Although the producer has already inserted the value in the stack to 25, the consumer first out of the stack is actually 4, not 25. It's like a mistake. But think about the stack, the stack and print statements are two parts, and not atomic operation, it should be normal to appear in this phenomenon.
Sample 3-1 Main {
Main T1 T2 started {
Main T1 T2 started}
Main wait T1 T2 End {
ThreadWork1 Run {
ThreadWork1 producer:0
ThreadWork2 Run {
ThreadWork1 producer:1
ThreadWork1 Producer:2
ThreadWork1 Producer:3
ThreadWork1 Producer:4
ThreadWork1 Producer:5
ThreadWork1 Producer:6
ThreadWork1 Producer:7
ThreadWork1 Producer:8
ThreadWork1 Producer:9
ThreadWork1 producer:10
ThreadWork1 producer:11
ThreadWork1 Producer:12
ThreadWork1 producer:13
ThreadWork1 producer:14
ThreadWork1 producer:15
ThreadWork1 producer:16
ThreadWork1 producer:17
ThreadWork1 producer:18
ThreadWork1 producer:19
ThreadWork1 producer:20
ThreadWork1 producer:21
ThreadWork1 producer:22
ThreadWork1 producer:23
ThreadWork1 producer:24
ThreadWork1 producer:25
ThreadWork2 consumer:16 =====4
THREADWORK2 consumer:625 =====25
THREADWORK2 consumer:576 =====24
THREADWORK2 consumer:529 =====23
ThreadWork1 producer:26
ThreadWork1 producer:27
ThreadWork1 producer:28



Concurrentbag an unordered collection in which the program can insert an element, or delete an element. When inserting into a collection in the same thread, it is highly efficient to delete elements.
  • ADD: inserting elements into the collection
  • TryTake: Remove the element from the collection and delete
  • Trypeek: Removes the element from the collection, but does not delete the element.

  • Examples of programs:
    Using system;using system.text;using system.threading.tasks;using system.collections.concurrent;namespace Sample4_3        _concurrent_bag{class Program {internal static concurrentbag<int> _testbag;            Class ThreadWork1//producer {public ThreadWork1 () {} public void run ()                {System.Console.WriteLine ("ThreadWork1 run {"); for (int i = 0; i < i++) {System.Console.WriteLine ("ThreadWork1 producer:" + I                    );                _testbag.add (i);            } System.Console.WriteLine ("ThreadWork1 Run}");  }} class ThreadWork2//consumer {public ThreadWork2 () {} public                void run () {int i = 0;                int ncnt = 0;                BOOL Isdequeuue = false;                System.Console.WriteLine ("ThreadWork2 run {"); FoR (;;)                    {Isdequeuue = _testbag.trytake (out i);   if (Isdequeuue) {System.Console.WriteLine ("THREADWORK2 Consumer:" + i * i + "                        ===== "+ i);                    ncnt++;                } if (ncnt = =) break;            } System.Console.WriteLine ("ThreadWork2 Run}");            }} static void StartT1 () {ThreadWork1 work1 = new ThreadWork1 ();        Work1.run ();            } static void StartT2 () {THREADWORK2 work2 = new ThreadWork2 ();        Work2.run ();            } static void Main (string[] args) {Task T1 = new Task (() = StartT1 ());            Task t2 = new Task (() = StartT2 ());            _testbag = new concurrentbag<int> ();            Console.WriteLine ("Sample 4-3 Main {"); Console.WriteLine ("Main T1 T2 Started {"); T1.            Start (); T2.            Start ();            Console.WriteLine ("Main T1 T2 started}");            Console.WriteLine ("Main wait T1 T2 end {");            Task.waitall (t1, T2);            Console.WriteLine ("Main wait T1 T2 End}");            Console.WriteLine ("Sample 4-3 Main}");        Console.readkey (); }    }}



    BlockingCollection a container that supports boundaries and blocking
      • ADD: Inserting elements into the container
      • TryTake: Remove the element from the container and delete
      • Trypeek: Removes the element from the container without deleting it.
      • CompleteAdding: Tells the container to add elements to complete. An exception occurs at this point if you still want to continue adding.
      • IsCompleted: tells the consumer thread that the producer thread is still running and the task is not completed.

    Sample program:
    In the program, the consumer thread fully uses while (!_testbcollection.iscompleted) as the judging condition for exiting the run. In Worker1, two statements are commented out, and when I is 50 the completeadding is set, but when you continue to insert the element, the system throws an exception, prompting that the insertion cannot continue.
    Using system;using system.text;using system.threading.tasks;using system.collections.concurrent;namespace Sample4_4        _concurrent_bag{class Program {internal static blockingcollection<int> _testbcollection;            Class ThreadWork1//producer {public ThreadWork1 () {} public void run ()                {System.Console.WriteLine ("ThreadWork1 run {"); for (int i = 0; i < i++) {System.Console.WriteLine ("ThreadWork1 producer:" + I                    );                    _testbcollection.add (i);                if (i = =)//_testbcollection.completeadding ();                } _testbcollection.completeadding ();            System.Console.WriteLine ("ThreadWork1 Run}");  }} class ThreadWork2//consumer {public ThreadWork2 () {} public           void Run () {     int i = 0;                int ncnt = 0;                BOOL Isdequeuue = false;                System.Console.WriteLine ("ThreadWork2 run {");                    while (!_testbcollection.iscompleted) {Isdequeuue = _testbcollection.trytake (out i); if (Isdequeuue) {System.Console.WriteLine ("ThreadWork2 consum                        ER: "+ i * i +" ===== "+ i);                    ncnt++;            }} System.Console.WriteLine ("ThreadWork2 Run}");            }} static void StartT1 () {ThreadWork1 work1 = new ThreadWork1 ();        Work1.run ();            } static void StartT2 () {THREADWORK2 work2 = new ThreadWork2 ();        Work2.run ();            } static void Main (string[] args) {Task T1 = new Task (() = StartT1 ());            Task t2 = new Task (() = StartT2 ()); _tesTbcollection = new blockingcollection<int> ();            Console.WriteLine ("Sample 4-4 Main {");            Console.WriteLine ("Main T1 T2 started {"); T1.            Start (); T2.            Start ();            Console.WriteLine ("Main T1 T2 started}");            Console.WriteLine ("Main wait T1 T2 end {");            Task.waitall (t1, T2);            Console.WriteLine ("Main wait T1 T2 End}");            Console.WriteLine ("Sample 4-4 Main}");        Console.readkey (); }    }}


    Of course, you can try to comment out the completeadding statement in Work1, at which point the WORK2 cannot exit.
    Concurrentdictionary is completely lock-free for read operations, and it uses fine-grained locks when many threads are modifying the data.
      • AddOrUpdate: If the key does not exist, the method adds a new key and value to the container and, if present, updates the existing key and value.
      • Getoradd: If the key does not exist, the method adds a new key and value to the container, returns an existing value if it exists, and does not add a new value.
      • TryAdd: Attempt to add a new key and value to the container.
      • TryGetValue: Attempts to get a value based on the specified key.
      • Tryremove: Attempt to delete the specified key.
      • Tryupdate: Conditionally updates the value corresponding to the current key.
      • GetEnumerator: Returns an enumerator that can traverse the entire container.


    Examples of programs:
    Using system;using system.text;using system.threading.tasks;using system.collections.concurrent;namespace Sample4_5         _concurrent_dictionary{class Program {internal static concurrentdictionary<int, int> _testdictionary; Class ThreadWork1//producer {public ThreadWork1 () {} public void run (                {System.Console.WriteLine ("ThreadWork1 run {"); for (int i = 0; i < i++) {System.Console.WriteLine ("ThreadWork1 producer:" + I                    );                _testdictionary.tryadd (i, I);            } System.Console.WriteLine ("ThreadWork1 Run}");  }} class ThreadWork2//consumer {public ThreadWork2 () {} public                void run () {int i = 0, ncnt = 0;                int nvalue = 0;                BOOL IsOk = false; System.Console.WriteLine ("ThreadWork2 run {");                    while (Ncnt < +) {IsOk = _testdictionary.trygetvalue (i, out nvalue);    if (IsOk) {System.Console.WriteLine ("THREADWORK2 Consumer:" + i * i + "                        ===== "+ i);                        Nvalue = Nvalue * Nvalue;                        _testdictionary.addorupdate (i, Nvalue, (key, value) = = {return value = Nvalue;});                        ncnt++;                    i++;            }} System.Console.WriteLine ("ThreadWork2 Run}");            }} static void StartT1 () {ThreadWork1 work1 = new ThreadWork1 ();        Work1.run ();            } static void StartT2 () {THREADWORK2 work2 = new ThreadWork2 ();        Work2.run ();            } static void Main (string[] args) {Task T1 = new Task (() = StartT1 ()); Taskt2 = new Task (() = StartT2 ());            bool Bisnext = true;            int nvalue = 0;            _testdictionary = new Concurrentdictionary<int, int> ();            Console.WriteLine ("Sample 4-5 Main {");            Console.WriteLine ("Main T1 T2 started {"); T1.            Start (); T2.            Start ();            Console.WriteLine ("Main T1 T2 started}");            Console.WriteLine ("Main wait T1 T2 end {");            Task.waitall (t1, T2);            Console.WriteLine ("Main wait T1 T2 End}"); foreach (var pair in _testdictionary) {Console.WriteLine (pair). Key + ":" + pair.            Value);                 } System.collections.generic.ienumerator<system.collections.generic.keyvaluepair<int, int>>            Enumer = _testdictionary.getenumerator (); while (bisnext) {bisnext = Enumer.                MoveNext (); Console.WriteLine ("Key:" + Enumer.                          Current.key +        "Value:" + Enumer.                Current.value); _testdictionary.tryremove (Enumer.            Current.key, out Nvalue);            } Console.WriteLine ("\n\ndictionary Count:" + _testdictionary.count);            Console.WriteLine ("Sample 4-5 Main}");        Console.readkey (); }    }}




    Concurrent collections of C # Parallel programming (. Net Framework 4.0)

    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.