zoukankan      html  css  js  c++  java
  • Parallel World 5 – Concurrent Collections (1)

    从本节开始,我们将要重点介绍如何解决并行运算中的哪两个问题。竞态问题其实就是一个共享数据的问题,所以许多资料也干脆把这个问题称为Share Data. 在多线程环境中我们知道很多解决这个问题的方法; .NET Framework 4 提供了System.Collections.Concurrent一个新的命名空间来解决这个问题。

    当开发人员在开发并行程序的过程中,需要在多个并行Task之间共享一个集合时,这个命名空间提供的Concurrent Collections是最佳选择;它们是线程安全的同时还提供了一个轻量级的同步机制。

    这个命名空间提供了以下个基本的并发集合 – ConcurrentBag, ConcurrentDictionary, ConcurrentQueue 、ConcurrentStack和BlockingCollection,OrderablePartitioner<TSource>、Partitioner、Partitioner<TSource>; 还有一个IProducerConsumerCollection<T>接口。前4个在这章中跟大家分享一下,后面几个将在后续文章中跟大家分享。

    I. ConcurrentQueue

       1: private const int NUM_MAX = 100;
       2:  
       3: static void Main(string[] args)
       4: {
       5:     ConcurrentQueue<Int32> concurrentQueue = new ConcurrentQueue<Int32>();
       6:    
       7:     try
       8:     {
       9:         Task.Factory.StartNew(() =>
      10:         {
      11:             for (int i = 0; i < NUM_MAX; i++)
      12:             {
      13:                 Console.WriteLine("###################: {0}", i);
      14:                 concurrentQueue.Enqueue(i);
      15:             }
      16:         });
      17:  
      18:         Task.Factory.StartNew(() => {
      19:             for (int i = 0; i < NUM_MAX; i++)
      20:             {
      21:                 int queueElement;
      22:                 bool success = concurrentQueue.TryDequeue(out queueElement);
      23:                 if (success)
      24:                 {
      25:                     Console.WriteLine("-----------------: {0}", queueElement);
      26:                 }
      27:             }
      28:         });
      29:     }
      30:     catch (System.AggregateException ex)
      31:     {
      32:         throw ex;
      33:     }
      34:  
      35:     Console.ReadLine();
      36: }

    Queue是遵循FIFO的集合,它提供了三个重要的方法

    TryPeek() 获得Queue中的第一个元素,但是并不把它从Queue中移除
    TryDequeue() 获得Queue中的第一个元素,并把它从Queue中移除
    Enqueue() 把一个元素放到Queue中

    执行上面的代码可以得到类似如下的结果:

    re

    II. ConcurrentStack

    Stack是遵循LIFO的集合,它提供了如下一些重要的方法:

    Push(T) 在栈顶插入一个元素
    PushRange(T[]) 在栈顶插入多个元素
    PushRange(T[], int startIndex, int count) 在栈顶插入多个元素,startIndex是指T[]从零开始的偏移量,从此处开始将元素插入到栈的顶部, count是指插入的数量
    TryPeek(out T result) 从栈顶返回一个元素,但是并不把它从栈顶移出
    TryPop(out T result) 从栈顶返回一个元素,并不把它从栈顶移除
    TryPopRange(out T[]) 将从栈顶部弹出的对象添加到的T[]
    TryPopRange(out T[]) 将从栈顶部弹出的对象添加到的T[],startIndex是指T[]从零开始的偏移量,从此处开始将元素插入到T[], count是指插入的数量

    III. ConcurrentBag

    ConcurrentBag无序集合

    TryPeek(out T result) 返回一个对象但不移除该对象,
    TryTake( out T result)

    返回一个对象并移除该对象

    IV. ConcurrentDictionary

    键/值对集合

    AddOrUpdate(TKey, Func<TKey, TValue>, Func<TKey, TValue, TValue>) 如果指定的键尚不存在,则将键/值对添加到 ConcurrentDictionary<TKey, TValue> 中;如果指定的键已存在,则更新 ConcurrentDictionary<TKey, TValue> 中的键/值对。
    AddOrUpdate(TKey, TValue, Func<TKey, TValue, TValue>) 如果指定的键尚不存在,则将键/值对添加到 ConcurrentDictionary<TKey, TValue> 中;如果指定的键已存在,则更新 ConcurrentDictionary<TKey, TValue> 中的键/值对。
    GetOrAdd(TKey, Func<TKey, TValue>) 如果指定的键尚不存在,则将键/值对添加到 ConcurrentDictionary<TKey, TValue> 中。
    GetOrAdd(TKey, TValue) 如果指定的键尚不存在,则将键/值对添加到 ConcurrentDictionary<TKey, TValue> 中。
    TryAdd(TKey, TValue) 尝试将指定的键和值添加到 ConcurrentDictionary<TKey, TValue> 中。
    TryRemove(TKey, out TValue) 尝试将制定的键和值移除,值将会被放到TResult中。如果移除成功,则返回true.

    这个集合中还有一些很有意思的方法,大家可以查看msdn来获得更多的帮助。

  • 相关阅读:
    nginx各版本全自动编译安装脚本
    kubernetes里面有时候centos源用不了
    centons6升级gcc和glibc版本
    容器下载的是centos8的镜像,scp出现packet_write_wait: Connection to **** port 22: Broken pipe 问题解决
    MNIST数据集手写体识别(MLP实现)
    BP 算法手动实现
    Python直接调用C库的printf()函数打印一条消息
    C/C++与Python实现混编(详细注释)
    MNIST数据集手写体数据还原为图片
    TensorFlow初识(MNIST数据集识别手写体)
  • 原文地址:https://www.cnblogs.com/wildboar/p/2080791.html
Copyright © 2011-2022 走看看