C#并行和多线程3 (同步机制下)

CountdownEvent

        //默认的容纳大小为“硬件线程“数
        static CountdownEvent cde = new CountdownEvent(Environment.ProcessorCount);
        static void Main(string[] args)
        {
            //加载User表需要5个任务
            var userTaskCount = 5;

            cde.Reset(userTaskCount);

            for(int i=0;i<userTaskCount;i++)
            {
                Task.Factory.StartNew((obj) =>
                {
                    LoadUser(obj);
                }, i);
            }

            //等待所有任务执行完毕
            cde.Wait();
            Console.WriteLine("\nUser表数据全部加载完毕!\n");

            var productTaskCount = 8;
            cde.Reset(productTaskCount);
            for (int i = 0; i < productTaskCount; i++)
            {
                Task.Factory.StartNew((obj) =>
                {
                    LoadProduct(obj);
                }, i);
            }
            cde.Wait();
            Console.WriteLine("\nProduct表数据全部加载完毕!\n");

            var orderTaskCount = 8;
            cde.Reset(productTaskCount);
            for (int i = 0; i < orderTaskCount; i++)
            {
                Task.Factory.StartNew((obj) =>
                {
                    LoadOrder(obj);
                }, i);
            }
            cde.Wait();
            Console.WriteLine("\nOrder表数据全部加载完毕!\n");

            Console.WriteLine("\n数据全部加载完毕\n");
            Console.ReadKey();

        }

        private static void LoadUser(object obj)
        {
            try
            {
                Console.WriteLine("当前任务:{0}正在加载User部分数据!", obj);
            }
            finally
            {
                cde.Signal();
            }
        }

        private static void LoadProduct(object obj)
        {
            try
            {
                Console.WriteLine("当前任务:{0}正在加载Product部分数据!", obj);
            }
            finally
            {
                cde.Signal();
            }
        }

        private static void LoadOrder(object obj)
        {
            try
            {
                Console.WriteLine("当前任务:{0}正在加载Order部分数据!", obj);
            }
            finally
            {
                cde.Signal();
            }
        }

我们看到有两个主要方法:Wait和Signal。每调用一次Signal相当于麻将桌上走了一个人,直到所有人都搓过麻将wait才给放行。 

SemaphoreSlim

        static SemaphoreSlim slim = new SemaphoreSlim(Environment.ProcessorCount, 12);
        static void Main(string[] args)
        {
            for(int i=0;i<12;i++)
            {
                Task.Factory.StartNew((obj) =>
                {
                    Run(obj);
                }, i);
            }
            Console.ReadKey();

        }

        private static void Run(object obj)
        {
            slim.Wait();
            Console.WriteLine("当前时间:{0}任务 {1}已经进入。", DateTime.Now, obj);

            Thread.Sleep(3000);
            slim.Release();
        }

ManualResetEventSlim

这个轻量级别采用的是"自旋等待“+”内核等待“,也就是说先采用”自旋等待的方式“等待,直到另一个任务调用set方法来释放它。如果迟迟等不到释放,那么任务就会进入基于内核的等待,所以说如果我们知道等待的时间比较短,采用轻量级的版本会具有更好的性能,原理大概就这样,下面举个小例子。

        static ManualResetEventSlim mrs = new ManualResetEventSlim(false, 2047);
        static void Main(string[] args)
        {
            for(int i=0;i<12;i++)
            {
                Task.Factory.StartNew((obj) =>
                {
                    Run(obj);
                }, i);
            }
            Console.WriteLine("当前时间:{0}我是主线程{1},你们这些任务都等2s执行吧:\n",
            DateTime.Now,
            Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(2000);

            mrs.Set();
            Console.ReadKey();

        }

        private static void Run(object obj)
        {
            mrs.Wait();
            Console.WriteLine("当前时间:{0}任务 {1}已经进入。", DateTime.Now, obj);

        }

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值