测试条件:

开启2个并行执行任务,往同一个list对象写入值

测试代码:

static int maxNum = ;

        static List<int> list = new List<int>();

        static void Main(string[] args)

        {

            //迭代次数

            int iterationNum = ;

            CodeTimer.Initialize();

            CodeTimer.Time("List是否是线程安全的呢?", iterationNum, new Action(ListIsThreadSafe));

            //Console.Write(sbIsThreadSafe.ToString());

            Console.Read();

        }

        private static void ListIsThreadSafe()

        {

            Parallel.For(, maxNum / , (i) =>

            {

                list.Add(i);

            });

            Parallel.For(maxNum /  + , maxNum, (i) =>

            {

                list.Add(i);

            });

        }

测试结果:

测试结论:

之所以会造成以上的结果是因为list对象不是线程安全。那该怎么办呢?

这时我们需要使用System.Collections.Concurrent命名空间下的类型来用于并行循环体内。

说明

BlockingCollection<T>

为实现 IProducerConsumerCollection<T> 的线程安全

集合提供阻止和限制功能。

ConcurrentBag<T>

表示对象的线程安全的无序集合。

ConcurrentDictionary<TKey, TValue>

表示可由多个线程同时访问的键值对的线程安全集合。

ConcurrentQueue<T>

表示线程安全的先进先出 (FIFO) 集合。

ConcurrentStack<T>

表示线程安全的后进先出 (LIFO) 集合。

OrderablePartitioner<TSource>

表示将一个可排序数据源拆分成多个分区的特定方式。

Partitioner

提供针对数组、列表和可枚举项的常见分区策略。

Partitioner<TSource>

表示将一个数据源拆分成多个分区的特定方式。

我们再来进行一次测试。

测试代码:

static int maxNum = ;   

        static ConcurrentQueue<int> safeList = new ConcurrentQueue<int>();

        static void Main(string[] args)

        {

            //迭代次数

            int iterationNum = ;

            CodeTimer.Initialize();

            CodeTimer.Time("ConcurrentQueue是否是线程安全的呢?", iterationNum, new Action(ListIsThreadSafe));

            //Console.Write(sbIsThreadSafe.ToString());

            Console.Read();

        }

        private static void ListIsThreadSafe()

        {

            Parallel.For(, maxNum / , (i) =>

            {

                safeList.Enqueue(i);

            });

            Parallel.For(maxNum /  + , maxNum, (i) =>

            {

                safeList.Enqueue(i);

            });

        }

测试结果:

测试结论:

ConcurrentQueue是线程安全的。在遇到多线程和并行开发时应该使用ConcurrentQueue而不是List.

疑问:为了确保对象线程安全,系统底层实现机制必定是要使用对象加锁和解锁的功能来确保对象安全,那么加锁和解锁是否会对性能造成影响呢?

我们再来进行一组测试:

测试条件:

(1)对100万个数据进行普通的循环运算然后添加到List集合对象中。

(2)对100万个数据进行并行循环运算然后添加到ConcurrentQueue集合对象中。

测试代码:

static int maxNum = ;

        static List<BigInteger> list = new List<BigInteger>();

        static ConcurrentQueue<BigInteger> safeList = new ConcurrentQueue<BigInteger>();

        static void Main(string[] args)

        {

            //迭代次数

            int iterationNum = ;

            CodeTimer.Initialize();

            CodeTimer.Time("普通的循环运算", iterationNum, new Action(NormalCompute));

            CodeTimer.Time("并行循环运算_1", iterationNum, new Action(ParallelCompute_1));

            CodeTimer.Time("并行循环运算_2", iterationNum, new Action(ParallelCompute_2));

            Console.Read();

        }

        private static void NormalCompute()

        {

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

            {

                Math.Pow(i, i + );

                list.Add(new BigInteger(i));

            }

        }

        private static void ParallelCompute_1()

        {

            Parallel.For(, maxNum, (i) =>

                {

                    Math.Pow(i, i + );

                    safeList.Enqueue(new BigInteger(i));

                });

        }

        private static void ParallelCompute_2()

        {

            Parallel.For(, maxNum / , (i) =>

            {

                Math.Pow(i, i + );

                safeList.Enqueue(new BigInteger(i));

            });

            Parallel.For(maxNum /  + , maxNum, (i) =>

            {

                Math.Pow(i, i + );

                safeList.Enqueue(new BigInteger(i));

            });

        }

测试结果:

 测试结论:

和我预期的结论是一样的,并行方式所耗费的时间更加的长。线程安全的加锁和解锁对性能的影响还是比较大的。

List是线程安全的吗?如果不是该怎么办呢?安全的List对性能的影响有多大呢?的更多相关文章

  1. Java线程并发中常见的锁

    随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...

  2. Java线程并发中常见的锁--自旋锁 偏向锁

    随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...

  3. NHibernate中Session的处理 线程不安全

    NHibernate中Session是线程不安全的,而且每次数据库操作 请求创建Session时对性能有些影响.在Windows应用中可以通过 [ThreadStatic]特性很简单的就可以实现线程安 ...

  4. C#异步编程(三)内核模式线程同步

    其实,在开发过程中,无论是用户模式的同步构造还是内核模式,都应该尽量避免.因为线程同步都会造成阻塞,这就影响了我们的并发量,也影响整个应用的效率.不过有些情况,我们不得不进行线程同步. 内核模式 wi ...

  5. iOS 25个性能优化/内存优化常用方法

    1. 用ARC管理内存 ARC(Automatic ReferenceCounting, 自动引用计数)和iOS5一起发布,它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存泄露.它自动为你 ...

  6. MST 001

    一.String,StringBuffer, StringBuilder 的区别是什么?String为什么是不可变的? 答:   1.String是字符串常量,StringBuffer和StringB ...

  7. (转)MySQL配置文件mysql.ini参数详解、MySQL性能优化

    本文转自:http://www.cr173.com/html/18331_1.html my.ini(Linux系统下是my.cnf),当mysql服务器启动时它会读取这个文件,设置相关的运行环境参数 ...

  8. 知方可补不足~sqlserver中的几把锁~续

    回到目录 之前写过相关的文章,对脏读,不可重复读,幻读都做了相当的研究,而今天在程序中又出现了这个问题,即当一条数据被update时,另一个线程同时发起了读的操作,这对于序列化级别的事务是不被允许的, ...

  9. iOS-------应用性能调优的25个建议和技巧

    性能对 iOS 应用的开发尤其重要,如果你的应用失去反应或者很慢,失望的用户会把他们的失望写满App Store的评论.然而由于iOS设备的限制,有时搞好性能是一件难事.开发过程中你会有很多需要注意的 ...

随机推荐

  1. Java学习笔记--AWT事件处理

    1.事件模型 在整个事件触发和相应的过程中,主要涉及一下3类对象 (1) 事件源 : 引起时间的GUI对象,如各类组件(Button,Label,TextField),容器组件(Frame,panel ...

  2. js各种进制数之间的转换

    计算机中常用的进制数有二进制.八进制.十进制.十六进制 一.十进制 to 其他 var x = 10; // 或定义其他值均可 x.toString(n); // n 代表要转换到的进制,比如n可以为 ...

  3. Oracle trunc函数

    --Oracle trunc()函数的用法/**************日期********************/1.select trunc(sysdate) from dual  --2011 ...

  4. android 显示特殊符号

    http://hsx9566.iteye.com/blog/1305052 在android上使用ASCII显示特殊符号 在xml中表示如下: <string name="symbol ...

  5. Sql Server 面试题

    1.用一条SQL语句 查询出每门课都大于80分的学生姓名 name   kecheng   fenshu 张三     语文       81张三     数学       75李四     语文   ...

  6. 《Programming WPF》翻译 第7章 7.我们进行到哪里了?

    原文:<Programming WPF>翻译 第7章 7.我们进行到哪里了? WPF提供了一个范围的高质量生成和合成服务.一组形状元素支持各种的绘图基础.一些笔刷类型是可利用的,对于决定如 ...

  7. juicer模板引擎使用

    http://www.juicer.name/ <script src="~/Scripts/jquery-1.8.2.min.js"></script> ...

  8. Hessian和Burlap入门教程

    一.简介 Hessian和Burlap是由Caucho Technology提供的基于HTTP协议的轻量级远程服务解决方案.他们都致力于借助尽可能简单那的API和通信协议来简化Web服务.    He ...

  9. {}+[] = ? 和 []+{} = ? 浅谈JS数据类型转换

    参加公司技术嘉年华第一季(前端.服务端)的间隙,陈导问了我一个问题:{}+[] 和 []+{}两个表达式的值分别是什么?根据我的理解我觉得结果应该都是"[object Object]&quo ...

  10. AC Milan VS Juventus(模拟)

    AC Milan VS Juventus Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Oth ...