C# 使用Parallel并行对比lock锁和ConcurrentQueue并发性能

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        private static object o = new object();

        private static Queue<Product> _ProductsNormal { get; set; }
        private static Queue<Product> _Products { get; set; }
        private static ConcurrentQueue<Product> _ConcurrenProducts { get; set; }

        /*  -------------------------------------------
         *  对比lock锁和ConcurrentQueue并发性能
         *  -------------------------------------------
            在.NET Framework4.0以后的版本中提供了命名空间:System.Collections.Concurrent 来解决线程安全和lock锁性能问题,通过这个命名空间,能访问以下为并发做好了准备的集合。
            1.BlockingCollection 与经典的阻塞队列数据结构类似,能够适用于多个任务添加和删除数据,提供阻塞和限界能力。
            2.ConcurrentBag 提供对象的线程安全的无序集合
            3.ConcurrentDictionary  提供可有多个线程同时访问的键值对的线程安全集合
            4.ConcurrentQueue   提供线程安全的先进先出集合
            5.ConcurrentStack   提供线程安全的后进先出集合
            这些集合通过使用比较并交换和内存屏障等技术,避免使用典型的互斥重量级的锁,从而保证线程安全和性能。
         */
        static void Main(string[] args)
        {
            #region 不启用并行计算使用锁lock
            //休眠重置校准结果
            Thread.Sleep(1000);
            _ProductsNormal = new Queue<Product>();

            Stopwatch swTaskn = new Stopwatch();//用于统计时间消耗的
            swTaskn.Start();
            Task tn1 = Task.Factory.StartNew(() => { AddProductsNormal(); });
            Task tn2 = Task.Factory.StartNew(() => { AddProductsNormal(); });
            Task tn3 = Task.Factory.StartNew(() => { AddProductsNormal(); });
            Task tn4 = Task.Factory.StartNew(() => { AddProductsNormal(); });
            Task tn5 = Task.Factory.StartNew(() => { AddProductsNormal(); });
            Task.WaitAll(tn1, tn2, tn3, tn4, tn5);
            swTaskn.Stop();

            Console.WriteLine("=========================不启用并行计算使用锁lock==================================");
            Console.WriteLine("Queue<Product> 当前数据量为:" + _ProductsNormal.Count);
            Console.WriteLine("Queue<Product> 执行时间为:" + swTaskn.ElapsedMilliseconds);
            #endregion

            #region 启用并行计算使用锁lock
            //休眠重置校准结果
            Thread.Sleep(1000);
            _Products = new Queue<Product>();

            Stopwatch swTask = new Stopwatch();//用于统计时间消耗的
            swTask.Start();
            Task t1 = Task.Factory.StartNew(() => { AddProducts(); });
            Task t2 = Task.Factory.StartNew(() => { AddProducts(); });
            Task t3 = Task.Factory.StartNew(() => { AddProducts(); });
            Task t4 = Task.Factory.StartNew(() => { AddProducts(); });
            Task t5 = Task.Factory.StartNew(() => { AddProducts(); });
            Task.WaitAll(t1, t2, t3, t4, t5);
            swTask.Stop();

            Console.WriteLine("=========================启用并行计算使用锁lock==================================");
            Console.WriteLine("Queue<Product> 当前数据量为:" + _Products.Count);
            Console.WriteLine("Queue<Product> 执行时间为:" + swTask.ElapsedMilliseconds);
            #endregion

            #region 启用并行计算不使用锁,使用4.0后提供的新功能
            //休眠重置校准结果
            Thread.Sleep(1000);
            _ConcurrenProducts = new ConcurrentQueue<Product>();

            Stopwatch swTask1 = new Stopwatch();
            swTask1.Start();
            Task tk1 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
            Task tk2 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
            Task tk3 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
            Task tk4 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
            Task tk5 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
            Task.WaitAll(tk1, tk2, tk3, tk4, tk5);
            swTask1.Stop();

            Console.WriteLine("===========启用并行计算不使用锁,使用4.0后提供的新功能==============================");
            Console.WriteLine("ConcurrentQueue<Product> 当前数据量为:" + _ConcurrenProducts.Count);
            Console.WriteLine("ConcurrentQueue<Product> 执行时间为:" + swTask1.ElapsedMilliseconds);
            #endregion

            Console.ReadLine();
        }


        static void AddProductsNormal()
        {            
            for (int i = 0; i < 1000000; i++)
            {
                Product product = new Product() { Name = "name" + i, Category = "Category" + i, SellPrice = 1 };
                lock (o)
                {
                    _ProductsNormal.Enqueue(product);
                }
            }
        }

        static void AddProducts()
        {
            Parallel.For(0, 1000000, (i) =>
            {
                Product product = new Product() { Name = "name" + i, Category = "Category" + i, SellPrice = 1 };
                lock (o)
                {
                    _Products.Enqueue(product);
                }
            });
        }

        static void AddConcurrenProducts()
        {
            Parallel.For(0, 1000000, (i) =>
            {
                Product product = new Product() { Name = "name" + i, Category = "Category" + i, SellPrice = 1 };
                _ConcurrenProducts.Enqueue(product);
            });
        }
    }

    class Product
    {
        public string Name { get; set; }
        public string Category { get; set; }
        public int SellPrice { get; set; }
    }
}

           /*
                Parallel在循环中的每个任务很简单,耗时很小时,并不具备优势,反而因为多线程开销导致效率低下。
                但在每个任务耗时较大时,应该使用Parallel,实现并发,具备很大的优势             
             */
            var dt = DateTime.Now;
            var rand = new Random();
            for (int i = 0; i < 200; i++)
            {
                Thread.Sleep(rand.Next(10, 100));
            }

            var standerTime = (DateTime.Now - dt).TotalMilliseconds;
            Console.WriteLine("标准的for循环,耗时{0}毫秒", standerTime);


            dt = DateTime.Now;
            int count = 0;
            Parallel.For(0, 200, i =>
            {
                //轻量级锁
                Interlocked.Increment(ref count);
                Thread.Sleep(rand.Next(10, 100));
            });
            Console.WriteLine("循环次数" + count);
            var parallelTime = (DateTime.Now - dt).TotalMilliseconds;
            Console.WriteLine("并行的for循环,耗时{0}毫秒", parallelTime);
            Console.WriteLine();

            if (standerTime <= parallelTime)
            {
                Console.WriteLine("----------标准的for循环节省{0}毫秒----------", (parallelTime - standerTime));
            }
            else
            {
                Console.WriteLine("----------并行的for循环节省{0}毫秒----------", (standerTime - parallelTime));
            }


            //Console.WriteLine(result.Result.ToString());
            Console.ReadLine();

 

发布了271 篇原创文章 · 获赞 287 · 访问量 309万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章