• c#集合类的线程安全


    即位于System.Collections命名空间下的集合,如Hashtable,ArrayList,Stack,Queue等.其均提供了线程同步的一个实现

    集合线程同步的问题

    public class Demo8
    {
        ArrayList list = new ArrayList(1000000);
        public Demo8()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(Task1));
            ThreadPool.QueueUserWorkItem(new WaitCallback(Task2));
        }
    
        public void Task1(object obj)
        {
            for (int i = 0; i < 500000; i++)
            {
                list.Add(i);
            }
    
            Console.WriteLine(DateTime.Now);
            Console.WriteLine("Task1 count {0}", list.Count);
        }
    
        public void Task2(object obj)
        {
            for (int i = 0; i < 500000; i++)
            {
                list.Add(i);
            }
    
            Console.WriteLine("Task2 count {0}", list.Count);
        }
    }

    image

    与预期结果不同

    调整为线程同步的集合

    每种数据类型都包含一个静态的Synchronized方法,如

    ArrayList list = ArrayList.Synchronized(new ArrayList(1000000));

    调整后的结果

    image
    以下为注意点:

    1. IsSynchronized判断集合是否为线程同步
    2. 其内部通过给SyncRoot属性加锁进行同步(即Monitor.Enter)

    自己控制锁

    public class Demo8
    {
        ArrayList list = new ArrayList(1000000);
        public Demo8()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(Task1));
            ThreadPool.QueueUserWorkItem(new WaitCallback(Task2));
        }
    
        public void Task1(object obj)
        {
            lock (list.SyncRoot)
            {
                for (int i = 0; i < 500000; i++)
                {
                    list.Add(i);
                }
            } 
           
            Console.WriteLine(DateTime.Now);
            Console.WriteLine("Task1 count {0}", list.Count);
        }
    
        public void Task2(object obj)
        {
            lock (list.SyncRoot)
            {
                for (int i = 0; i < 500000; i++)
                {
                    list.Add(i);
                }
            }
            Console.WriteLine("Task2 count {0}", list.Count);
        }
    }

    image

    这样的结果显然好看点.内部实现是在Add方法中做锁定.效果自然不是很好.

    其他集合类也是类似的操作

    参考:
    http://www.cnblogs.com/Mainz/archive/2008/04/06/CSharp_HashTable_Dictionary_ArrayList_Threadsafe.html

    泛型集合

    可以看到原非泛型集合内部的线程同步集合,在每次操作均采用锁操作,但我们并非每个操作都需要锁,比如上面的2个线程操作.只需要2个锁就可以了,但使用内部集合的话则需要锁很多次,带来了性能问题.在.net 2.0泛型集合中,内部不再支持线程同步的集合,即使内部实现了线程同步的集合如List<T>的实现也为开发出来,即把lock的这个操作转嫁给开发者上面了.其实这样反而可以让我们更加了解线程同步的问题,如果真有需要的话,也可以自己实现一个了...

  • 相关阅读:
    vue-router的基本使用
    SQL Server加密存储过程的破解
    IIS绑定Active Directory账号自动登录网站的方法
    .Net Install类的Install、Commit等事件触发顺序
    正态分布公式
    HDU4417 Super Mario
    CodeChef
    Gym101630C Connections
    CF916C
    CF912D Fishes
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/1897534.html
Copyright © 2020-2023  润新知