zoukankan      html  css  js  c++  java
  • .NET Framework 4 中的并行编程9---线程安全集合类

    原文转载自: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 = 0; i < 1000; i++)
    
                {
    
                    sharedQueue.Enqueue(i);
    
                }
    
     
    
                int itemCount = 0;
    
     
    
                Task[] tasks = new Task[10];
    
                for (int i = 0; i < tasks.Length; i++)
    
                {
    
                    tasks[i] = new Task(() =>
    
                    {
    
                        while (sharedQueue.Count > 0)
    
                        {
    
                            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 = 0; i < 1000; i++)
    
                {
    
                    sharedBag.Add(i);
    
                }
    
     
    
                int itemCount = 0;
    
                Task[] tasks = new Task[10];
    
    
                for (int i = 0; i < tasks.Length; i++)
    
                {
    
                    tasks[i] = new Task(() =>
    
                    {
    
                       while(sharedBag.Count>0)
    
                        {
    
                            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>[10];
    
                for (int i = 0; i < tasks.Length; i++)
    
                {
    
                    sharedDict.TryAdd(i, account.Balance);
    
                    tasks[i] = new Task<int>((keyObj) =>
    
                    {
    
                        int currentValue;
    
                        bool gotValue;
    
                        for (int j = 0; j < 1000; j++)
    
                        {
    
                            gotValue = sharedDict.TryGetValue(keyObj, out currentValue);
    
                            sharedDict.TryUpdate(keyObj, currentValue + 1, 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 = 0; i < tasks.Length; i++)
    
                {
    
                    account.Balance += tasks[i].Result;
    
                }
    
     
    
                Console.WriteLine("Expected value {0}, Balance: {1}", 10000, account.Balance);
    
                Console.WriteLine("Press enter to finish");
    
                Console.ReadLine();
    
    }

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

  • 相关阅读:
    QT设置窗口屏幕居中
    屏蔽ubuntu桌面鼠标右键以及Ctrl Alt F*
    ubuntu12.04 U盘自动挂载配置
    最受欢迎的15个Python开源框架
    异步非阻塞IO的Python Web框架--Tornado
    RabbitMQ RPC问题
    petapoco模板修改
    事件&表达式
    .net core2 单元测试
    检查邮箱IP是否在国际反垃圾邮件组织的黑名单中
  • 原文地址:https://www.cnblogs.com/colder/p/4485935.html
Copyright © 2011-2022 走看看