原文转载自:http://www.cnblogs.com/xray2005/archive/2011/10/11/2206745.html

在.Net 4中,新增System.Collections.Concurrent 命名空间中提供多个线程安全集合类,这些类提供了很多有用的方法用于访问集合中的元素,从而可以避免使用传统的锁(lock)机制等方式来处理并发访问集合.因此当有多个线程并发访问集合时,应首先考虑使用这些类代替 System.Collections 和 System.Collections.Generic 命名空间中的对应类型.具体如下:

1. ConcurrentQueue

表示线程安全的先进先出(FIFO)队列.代码如下:

           ConcurrentQueue<int> sharedQueue = new ConcurrentQueue<int>();

            for (int i = ; i < ; i++)

            {

                sharedQueue.Enqueue(i);

            }

            int itemCount = ;

            Task[] tasks = new Task[];

            for (int i = ; i < tasks.Length; i++)

            {

                tasks[i] = new Task(() =>

                {

                    while (sharedQueue.Count > )

                    {

                        int queueElement;

                        bool gotElement = sharedQueue.TryDequeue(out queueElement);

                        if (gotElement)

                        {

                            Interlocked.Increment(ref itemCount);

                        }

                    }

                });

                tasks[i].Start();

            }

            Task.WaitAll(tasks);

            Console.WriteLine("Items processed:{0}", itemCount);

            Console.WriteLine("Press Enter to finish");

            Console.ReadLine();

该类有两个重要的方法用来访问队列中的元素.分别是:

Ø TryDequeue 尝试移除并返回位于队列头开始处的对象.

Ø TryPeek尝试返回位于队列头开始处的对象但不将其移除.

现在,在多任务访问集合元素时,我们只需要使用TryDequeue或TryPeek方法,就可以安全的访问集合中的元素了.

2. ConcurrentStack

表示线程安全的后进先出(LIFO)栈.它也有几个有用的方法,分别是:

Ø TryPeek:尝试返回栈顶处的元素,但不移除.

Ø TryPop: 尝试返回栈顶处的元素并移除.

Ø TryPopRange: 尝试返回栈顶处开始指定范围的元素并移除.

在访问集合中的元素时,我们就可以上述方法.具体代码实例于上面的ConcurrentQueue类似,就不重复了.

3. ConcurrentBag

实现的是一个无序的集合类.代码如下:

ConcurrentBag<int> sharedBag = new ConcurrentBag<int>();

            for (int i = ; i < ; i++)

            {

                sharedBag.Add(i);

            }

            int itemCount = ;

            Task[] tasks = new Task[];

            for (int i = ; i < tasks.Length; i++)

            {

                tasks[i] = new Task(() =>

                {

                   while(sharedBag.Count>)

                    {

                        int queueElement;

                        bool gotElement = sharedBag.TryTake(out queueElement);

                       if (gotElement)

                            Interlocked.Increment(ref itemCount);

                    }

                });

                tasks[i].Start();

            }

            Task.WaitAll(tasks);

            Console.WriteLine("Items processed:{0}", itemCount);

            Console.WriteLine("Press Enter to finish");

            Console.ReadLine();

该类有两个重要的方法用来访问队列中的元素.分别是:

Ø TryTake 尝试移除并返回位于队列头开始处的对象.

Ø TryPeek尝试返回位于队列头开始处的对象但不将其移除.

4. ConcurrentDictionary

实现的是一个键-值集合类.它提供的方法有:

Ø TryAdd:尝试向集合添加一个键-值

Ø TryGetValue:尝试返回指定键的值.

Ø TryRemove:尝试移除指定键处的元素.

Ø TryUpdate:尝试更新指定键的值.

代码如下:

class BankAccount

        {

            public int Balance

            {

                get;

                set;

            }

        }

 static void DictTest()

        {

            BankAccount account = new BankAccount();

            ConcurrentDictionary<object, int> sharedDict = new ConcurrentDictionary<object, int>();

            Task<int>[] tasks = new Task<int>[];

            for (int i = ; i < tasks.Length; i++)

            {

                sharedDict.TryAdd(i, account.Balance);

                tasks[i] = new Task<int>((keyObj) =>

                {

                    int currentValue;

                    bool gotValue;

                    for (int j = ; j < ; j++)

                    {

                        gotValue = sharedDict.TryGetValue(keyObj, out currentValue);

                        sharedDict.TryUpdate(keyObj, currentValue + , currentValue);

                    }

                    int result;

                    gotValue = sharedDict.TryGetValue(keyObj, out result);

                    if (gotValue)

                    {

                        return result;

                    }

                    else

                    {

                        throw new Exception(String.Format("No data item available for key {0}", keyObj));

                    }

                }, i);

                tasks[i].Start();

            }

            for (int i = ; i < tasks.Length; i++)

            {

                account.Balance += tasks[i].Result;

            }

            Console.WriteLine("Expected value {0}, Balance: {1}", , account.Balance);

            Console.WriteLine("Press enter to finish");

            Console.ReadLine();

}

通过上述提供的安全类,我们可以方便的并发访问集合中的元素,而不需要以前的Synchronized方法或者lock(SyncRoot)等处理方式.

.NET Framework 4 中的并行编程9---线程安全集合类的更多相关文章

  1. .Net中的并行编程-2.ConcurrentStack的实现与分析

    在上篇文章<.net中的并行编程-1.基础知识>中列出了在.net进行多核或并行编程中需要的基础知识,今天就来分析在基础知识树中一个比较简单常用的并发数据结构--.net类库中无锁栈的实现 ...

  2. .Net中的并行编程-3.ConcurrentQueue实现与分析

    在上文<.Net中的并行编程-2.ConcurrentQueue的实现与分析> 中解释了无锁的相关概念,无独有偶BCL提供的ConcurrentQueue也是基于原子操作实现, 由于Con ...

  3. .Net中的并行编程-6.常用优化策略

                本文是.Net中的并行编程第六篇,今天就介绍一些我在实际项目中的一些常用优化策略.      一.避免线程之间共享数据 避免线程之间共享数据主要是因为锁的问题,无论什么粒度的锁 ...

  4. .Net中的并行编程-5.流水线模型实战

    自己在Excel整理了很多想写的话题,但苦于最近比较忙(其实这是借口).... 上篇文章<.Net中的并行编程-4.实现高性能异步队列>介绍了异步队列的实现,本篇文章介绍我实际工作者遇到了 ...

  5. .Net中的并行编程-4.实现高性能异步队列

    上文<.Net中的并行编程-3.ConcurrentQueue实现与分析>分析了ConcurrentQueue的实现,本章就基于ConcurrentQueue实现一个高性能的异步队列,该队 ...

  6. .Net中的并行编程-1.路线图(转)

    大神,大神,膜拜膜拜,原文地址:http://www.cnblogs.com/zw369/p/3834559.html 目录 .Net中的并行编程-1.路线图 分析.Net里线程同步机制 .Net中的 ...

  7. Python中的并行编程速度

    这里主要想记录下今天碰到的一个小知识点:Python中的并行编程速率如何? 我想把AutoTool做一个并行化改造,主要目的当然是想提高多任务的执行速度.第一反应就是想到用多线程执行不同模块任务,但是 ...

  8. Python中的多线程编程,线程安全与锁(二)

    在我的上篇博文Python中的多线程编程,线程安全与锁(一)中,我们熟悉了多线程编程与线程安全相关重要概念, Threading.Lock实现互斥锁的简单示例,两种死锁(迭代死锁和互相等待死锁)情况及 ...

  9. .Net中的并行编程-1.路线图

    最近半年一直研究用.net进行并行程序的开发与设计,再研究的过程中颇有收获,所以画了一个图总结了一下并行编程的基础知识点,这些知识点是并行编程的基础,有助于我们编程高性能的程序,里面的某些结构实现机制 ...

随机推荐

  1. php 支持断点续传的文件下载类

    php 支持断点续传的文件下载类 分类: php class2013-06-30 17:27 17748人阅读 评论(6) 收藏 举报 php断点续传下载http测试 php 支持断点续传,主要依靠H ...

  2. jquery用法大全

    jQuery 选择器 选择器                  实例                                   选取 *                          $ ...

  3. img base64

    <?php header('Content-type:text/html;charset=utf-8'); //读取图片文件,转换成base64编码格式 $image_file = './429 ...

  4. design the relations

    Computer Science An Overview _J. Glenn Brookshear _11th Edition A pivotal step in designing a relati ...

  5. delphi 向其他程序发送模拟按键

    向其他程序发送模拟按键: 1.用keybd_event: varh : THandle;beginh := FindWindow('TFitForm', '1stOpt - [Untitled1]') ...

  6. nodejs 执行shell 命令

    有需要从前端操作服务器执行shell命令的需求 建立一个process.js文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var process =  ...

  7. JBPM3.2 TABLE

    http://m.blog.csdn.net/blog/longjie_happy/9343349

  8. VC更换图标文件

    步骤 1. 删除图标 2. 在VC中移除图标 3. 用新图标替换原来图标 4. 添加图标到VC 5. 重新编译 参考文档 http://www.cnblogs.com/BloodAndBone/arc ...

  9. useful tools, excel import mysql,swagger

    http://www.th7.cn/Program/java/201602/765943.shtml------swagger http://blog.csdn.net/csfreebird/arti ...

  10. HBase的数据迁移(含HDFS的数据迁移)

    1.启动两个HDFS集群 hadoop0,hadoop1,都是伪分布式的集群 2.启动hadoop3的zookeeper与hbase 注意点:需要开启yarn服务,因为distcp需要yarn. 3. ...