zoukankan      html  css  js  c++  java
  • C# 线程同步之排它锁/Monitor监视器类

    一、Monitor类说明,提供同步访问对象的机制。

    1.位于System.Threading命名空间下,mscorlib.dll程序集中。

    2.Monitor通过获取和释放排它锁的方式实现多线程的同步问题。

    3.Monitor实现当前进程内的多线程的同步,和lock语句的功能类似。

    4.当前为静态类,使用简单

    5.依赖的锁定对象和lock语句中类似,同样需要引用类型、建议私有、只读、静态

    定义代码:

        //
        // 摘要:
        //     提供同步访问对象的机制。
        [ComVisible(true)]
        public static class Monitor

    二、常用方法说明

    1.Enter(obj)方法 在指定对象上获取排它锁。

    2.Exit(obj)   释放指定对象上的排他锁。

    3.IsEntered(obj) 判断当前线程是否已经持有排它锁

    4.TryEnter(object obj, TimeSpan timeout)  在指定的时间量内尝试获取指定对象上的排他锁。

    5.Wait(object obj) 释放对象上的锁并阻止当前线程,直到它重新获取该锁。

    6.Pulse(object obj) 通知等待队列中的线程锁定对象状态的更改。

    7.PulseAll(object obj)  通知所有的等待线程对象状态的更改。

    三、示例说明一:

    说明:多线程累加数值,解决同步问题

    private readonly static object _MyLock = new object();
    static int Count = 0;
    static void CountAdd()
    {
        Monitor.Enter(_MyLock); //获取排它锁
        Count++;
        Console.WriteLine(Count);
        if (Count == 10)
        {
            Count = 0;
        }
        Monitor.Exit(_MyLock); //释放排它锁
    }
    public static void TestOne()
    {
        //启动4个线程,累加Count
        for (int i = 0; i < 4; i++)
        {
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    CountAdd();
                    Thread.Sleep(500 * i);
                }
            });
        }
    }

    1.如果不使用排它锁处理,会出现数据异常

    2.使用锁定结果会正常

    四、借助于using(){} 块实现锁定处理

    1.此场景在事务处理中可能会用到,保证同一个事务,如果一个线程开启操作,其他线程对当前事务操作等待。

    2.此场景对于外部使用,不需要考虑多线程问题

    1.继承了IDisposable接口的封装

        class AddHelper : IDisposable
        {
    
            private readonly static object _MyLock = new object();
            static int Count = 0;
            public AddHelper()
            {
                //启用排它锁
                Monitor.Enter(_MyLock);
            }
            public void AddCount()
            {
                Count++;
                Console.WriteLine(Count);
                if (Count == 10)
                {
                    Count = 0;
                }
            }
            public void Dispose()
            {
                //释放排它锁
                Monitor.Exit(_MyLock);
            }
        }

    2.调用代码块

    public static void TestTwo()
    {
        //启动4个线程,累加Count
        for (int i = 0; i < 4; i++)
        {
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    //如果不使用排他锁处理,会出现数据异常
                    //AddHelper _add = new AddHelper();
                    //_add.AddCount();
    
                    //将排他锁处理封装
                    using (AddHelper _add = new AddHelper())
                    {
                        _add.AddCount();
                    }
                    Thread.Sleep(500 * i);
                }
            });
        }
    }

    更多参考:

    C# lock关键词/lock语句块、线程锁

     C# using 关键字使用整理

     EntiryFramework中事务操作(二)

    官方参考:https://msdn.microsoft.com/zh-cn/library/system.threading.monitor.aspx

  • 相关阅读:
    #背包#nssl 1488 上升子序列
    #环#nssl 1487 图
    #分治#JZOJ 4211 送你一颗圣诞树
    #概率,dp#JZOJ 4212 我想大声告诉你
    #并查集#JZOJ 4223 旅游
    #dp#nssl 1478 题
    #对顶堆#nssl 1477 赛
    #线段树,离散#nssl 1476 联
    #折半搜索,状压dp#nssl 1471 Y
    #并查集,线性筛#nssl 1470 X
  • 原文地址:https://www.cnblogs.com/tianma3798/p/6290712.html
Copyright © 2011-2022 走看看