• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

[深夜原创]C#Monitor通知机制的一个有趣的实例

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

主要使用Monitor类,对一个对象进行等待和通知的操作

        static void Main(string[] args)
        {
            //Task启动等待对象
            object taskStartSyncRoot = new object();

            //多线程等待对象
            object syncRoot = new object();

            //多线程全部进入等待状态对象
            object parallelStartSyncRoot = new object();

            lock (taskStartSyncRoot)
            {
                Task.Factory.StartNew(() =>
                {
                    lock (parallelStartSyncRoot)
                    {
                        lock (taskStartSyncRoot)
                        {
                            //通知Task已经启动完毕
                            Monitor.Pulse(taskStartSyncRoot);
                        }

                        Console.WriteLine("Wait all parallel task started.");

                        //等待所有并行任务已经进行等待状态,并释放parallelStartSyncRoot锁
                        Monitor.Wait(parallelStartSyncRoot);

                        lock (syncRoot)
                        {
                            //通知所有并行任务syncRoot已经释放
                            Monitor.PulseAll(syncRoot);
                            Console.WriteLine("All syncRoot waiter notified.");
                        }
                    }
                });

                //等待Task启动完毕,并释放taskStartSyncRoot对象锁
                Monitor.Wait(taskStartSyncRoot);
            }

            //并行等待任务计数器,当该计数器为10时,则通知所有并行任务已经进入等待状态
            int counter = 0;

            Parallel.For(0, 10, (i) =>
            {
                lock (syncRoot)
                {
                    //使用原子锁增加counter,当计数器为10时代表所有并行任务已经启动
                    if (Interlocked.Increment(ref counter) == 10)
                    {
                        lock (parallelStartSyncRoot)
                        {
                            //通知并行任务已经全部启动,并释放parallelStartSyncRoot锁
                            Monitor.Pulse(parallelStartSyncRoot);
                        }
                    }

                    Console.WriteLine(string.Format("[{0}] Waiting For syncRoot notify.", i));

                    //等待syncRoot通知,并释放syncRoot锁
                    Monitor.Wait(syncRoot);
                    Console.WriteLine(string.Format("[{0}] syncRoot notify received.", i));
                }
            });

            Console.Read();
        }

该程序是个多线程的应用,程序的逻辑将会严格按照以下顺序执行

(1)[主线程] 启动Task线程,等待taskStartSyncRoot,暂时释放syncRoot锁

(2)[TASK线程] 锁住parallelStartSyncRoot 和 taskStartSyncRoot(这里会等待主线程进入Wait状态),通知taskStartSyncRoot已经启动

(3)[TASK线程] 等待parallelStartSyncRoot,暂时释放parallelStartSyncRoot锁

(4)[Parallel子线程] Parallel并行任务启动,并且等待syncRoot,暂时释放syncRoot锁

(5)[最后一个Parallel子线程] 通知parallelStartSyncRoot已经全部启动

(6)[TASK线程] 等待锁syncRoot

(7)[最后一个Parallel子线程] 等待syncRoot,这时会暂时释放syncRoot锁

(8)[TASK线程] 获得syncRoot锁,并且通知(Monitor.PulseAll)所有syncRoot等待者(所有并行任务)。

程序的执行结果:

总结:要理解该多线程程序,必须要理解这三个锁对象的操作,以及通知机制的应用,从而可以让Task和多个并行任务有序的进行执行,大家在这里需要掌握几个知识点:

(1)在Monitor.Wait对象时必须获得目标对象的锁,以确保进入临界状态

(2)Monitor.Wait方法调用时,会将目标对象锁释放,在Wait完成时会重新获得该锁

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#语法之virtual关键字发布时间:2022-07-14
下一篇:
安装navicat后C盘多了好多链接文件夹发布时间:2022-07-14
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap