C#之:线程同步 Monitor类

Monitor:提供同步访问对象的机制。

其实lock关键字就是对Monitor的简化调用,lock最终就编译成Monitor,因此一般不不直接用Monitor类
与lock 语句相比较 Monitor 类是主要优点是:可以添加一个等待被锁定的超时值。这样就不会无限期的等待被锁定。
但是 Monitor 必须手动释放锁。一般把代码写在 try/finally中。

例:

        static int number = 5000;
        private static object locker1 = new object();
        static void ChangeNumber(string str)
        {
            Monitor.Enter(locker1);//等待没有人锁定locker对象,我就锁定它,然后继续执行
            try
            {
                int num = number - 1;
                number = num;
                Thread.Sleep(1);
                Console.WriteLine(str + " 改变数据 :" + number);
            }
            finally
            {
                Monitor.Exit(locker1);//释放locker1对象的锁
            }
            
        }

        static void Main(string[] args)
        {
            Thread t1 = new Thread(() =>
            {
                for (int i = 0; i < 1000; i++)
                {
                    ChangeNumber("t1");
                }
            });
            Thread t2 = new Thread(() => {
                for (int i = 0; i < 1000; i++)
                {
                    ChangeNumber("t2");
                }
            });
            //t1.IsBackground = true;
            //t2.IsBackground = true;
            t1.Start();
            t2.Start();
            Thread.Sleep(5000);//等待线程执行完毕

            Console.WriteLine("改变后:"+number);

            Console.ReadKey();
        }

在这里插入图片描述

Monitor 超时设定方法:

static int number = 5000;
        private static object locker1 = new object();
        private static object locker2 = new object();
        
        static void ChangeNumber(string str)
        {
            //传入超时时间,指定等待被锁定的最长时间,如果对象被锁定,TryEnter()会把布尔的引用参数设置为 true 并同步地访问由对象 locker1 锁定的状态。如果另一个线程锁定 locker1 的时间超过 5 毫秒,TryEnter()方法就会把变量 flag 设置为 false,线程不再等待,而是执行其他操作,也许在以后,该线程会尝试再次获得锁定
            bool flag = false;
            Monitor.TryEnter(locker1,5,ref flag);
            if(flag)
            {
                try
                {
                    int num = number - 1;
                    number = num;
                    Thread.Sleep(1);
                    Console.WriteLine(str + " 改变数据 :" + number);
                }
                finally
                {
                    Monitor.Exit(locker1);//释放locker1对象的锁
                }
            }
            else
            {
                Console.WriteLine("已超时!");
            }
           
            
        }

        static void Main(string[] args)
        {
            Thread t1 = new Thread(() =>
            {
                for (int i = 0; i < 1000; i++)
                {
                    ChangeNumber("t1");
                }
            });
            Thread t2 = new Thread(() => {
                for (int i = 0; i < 1000; i++)
                {
                    ChangeNumber("t2");
                }
            });
            //t1.IsBackground = true;
            //t2.IsBackground = true;
            t1.Start();
            t2.Start();
            Thread.Sleep(5000);//等待线程执行完毕

            Console.WriteLine("改变后:"+number);

            Console.ReadKey();
        }

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值