List 集合线程安全测试

Posted 仰光博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了List 集合线程安全测试相关的知识,希望对你有一定的参考价值。

      最近在做一些代码整理工作,涉及到List 线程安全问题,查了一些资料。网上有些资料说List 增减成员(Add , Remove) 是安全的,但不保证成员属性值访问安全性,及禁止对 List 跨线程遍历访问, 如 foreach 遍历。
可以想象,有些跨线程操作(Add , Remove)List 集合时, 恰好 另一个线程正在通过 foreach遍历, 这时会抛出异常) 。 有改进方案用 for 替代 foreach ,这样仍会报下标越界错误。
因此 , 跨线程遍历list 不安全毋庸置疑。 对List 增减成员是否安全,需要验证才知道。

如下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace testQueue
{
    class Program
    {
        static List<int> list = new List<int>();
        static ManualResetEvent[] manu;
        static object LockList = new object();

        static void Main(string[] args)
        {
            manu = new ManualResetEvent[2];
            manu[0] = new ManualResetEvent(false);
            manu[1] = new ManualResetEvent(false);

            ThreadPool.QueueUserWorkItem(new WaitCallback(Task1));
            ThreadPool.QueueUserWorkItem(new WaitCallback(Task2));

            //等待完成
            ManualResetEvent.WaitAll(manu);

            //统计结果:
            Console.WriteLine("count:{0}", list.Count);

            Console.ReadKey();
        }

        public static void Task1(object obj)
        {
            // lock (LockList)
            //  {
            for (int i = 0; i < 5000000; i++)
            {
                list.Add(i);
            }
            //  }

            Console.WriteLine("Task1 complete!");
            manu[0].Set();
        }

        public static void Task2(object obj)
        {
            //  lock (LockList)
            // {
            for (int i = 0; i < 5000000; i++)
            {
                list.Add(i);
            }
            // }
            Console.WriteLine("Task2 complete!");
            manu[1].Set();
        }
    }
}

 

结果:

 

我们知道, List 集合大小是动态分配的,此处表明,分配List 大小,与对 List 操作 , 应保证在同一线程。  为了避免List 运行中分配大小,在初使化时,设置了List 大小:

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

 

再看看结果:

增加线程锁结果:

 

结论:

     此处表明,使用 List 跨线程操作,增减成员也需加锁。否则会有各种问题。
有关线程集合安全访问, 微软在 .Net Framework 4 时,提供了线程安全集合命名空间:

 System.Collections.Concurrent

 

以上是关于List 集合线程安全测试的主要内容,如果未能解决你的问题,请参考以下文章

线程安全的集合

juc学习四(集合不安全问题)

JAVA集合

[转]JAVA集合

21 张图 | 带你领略集合的 线程不安全

java集合类源码分析之List