• Monitor类实现线程同步


    Monitor类实现线程同步

    一、简介

    Lock关键字是Monitor的一种替换用法,lock在IL代码中会被翻译成Monitor. 

             lock (obj)
                {
                    //代码段
                }
            //就等同于
             Monitor.Enter(obj);
                //代码段
             Monitor.Exit(obj); 

    Monitor的常用属性和方法:
    Enter(Object) 在指定对象上获取排他锁。
    Exit(Object) 释放指定对象上的排他锁。
    Pulse 通知等待队列中的线程锁定对象状态的更改。
    PulseAll 通知所有的等待线程对象状态的更改。
    TryEnter(Object) 试图获取指定对象的排他锁。
    TryEnter(Object, Boolean) 尝试获取指定对象上的排他锁,并自动设置一个值,指示是否得到了该锁。
    Wait(Object) 释放对象上的锁并阻止当前线程,直到它重新获取该锁。
    常用的方法有两个
    Monitor.Enter(object)方法是获取锁
    Monitor.Exit(object)方法是释放锁
    这就是Monitor最常用的两个方法,在使用过程中为了避免获取锁之后因为异常,致锁无法释放,所以需要在try{} catch(){}之后的finally{}结构体中释放锁(Monitor.Exit())。

    二、代码

    1.Enter(Object)案例

    Enter(Object)的用法很简单,看代码

     class Program
        {
            static void Main(string[] args)
            {
                Thread threadA = new Thread(ThreadMethod);
                threadA.Name = "A";
                Thread threadB = new Thread(ThreadMethod); 
                threadB.Name = "B";
                threadA.Start();
                threadB.Start();
                Thread.CurrentThread.Name = "C";
                ThreadMethod();
                Console.ReadKey();
            }
    
            static object obj = new object();
            public static void ThreadMethod()
            {
                Monitor.Enter(obj); //Monitor.Enter(obj)  鎖定对象
                try
                {
                    for (int i = 1; i <= 10; i++)
                    {
                        Console.Write(Thread.CurrentThread.Name + ":" + i + "	");
                    }
                    Console.WriteLine();
                }
                catch (Exception ex)
                {
    
                }
                finally
                {
                    Monitor.Exit(obj);  //  Monitor.Exit(obj);  释放鎖定对象
                }
            }
        }

    执行结果:

    2.TryEnter(Object)TryEnter()案例

    TryEnter(Object)和TryEnter()方法在尝试获取一个对象上的显式锁方面和 Enter()方法类似。然而,它不像Enter()方法那样会阻塞执行。如果线程成功进入关键区域那么TryEnter()方法会返回true. 和试图获取指定对象的排他锁。看下面代码演示:

     class Program
        {
            static void Main(string[] args)
            {
                Thread threadA = new Thread(ThreadMethod);
                threadA.Name = "A";
                Thread threadB = new Thread(ThreadMethod); 
                threadB.Name = "B";
                threadA.Start();
                threadB.Start();
                Thread.CurrentThread.Name = "C";
                ThreadMethod();
                Console.ReadKey();
            }
    
            static object obj = new object();
            public static void ThreadMethod()
            {
                bool flag = Monitor.TryEnter(obj, 1000);
                //设置1S的超时时间,如果在1S之内没有获得同步锁,则返回false
                //上面的代码设置了锁定超时时间为1秒,也就是说:
                //如果在1秒中后,lockObj还未被解锁,TryEntry方法就会返回false,如果在1秒之内,lockObj被解锁,TryEntry返回true。我们可以使用这种方法来避免死锁
                try
                {
                    if (flag)
                    {
                        for (int i = 1; i <= 10; i++)
                        {
                            Console.Write(Thread.CurrentThread.Name + ":" + i + "	");
                        }
                        Console.WriteLine();
                    }
                       
                }
                catch (Exception ex)
                {
    
                }
                finally
                {
                    if (flag)
                        Monitor.Exit(obj); //  Monitor.Exit(obj);  释放鎖定对象
                }
            }
        }

    执行结果:

    通过Monitor.TryEnter(monster, 1000),该方法也能够避免死锁的发生,我们上面的例子用到的是该方法的重载,Monitor.TryEnter(Object,Int32)。

    三、总结

    为了能避免多线程死锁的发生,尽量用TryEnter(Object)和TryEnter()方法在尝试获取一个对象上的显式锁。


    技术的发展日新月异,随着时间推移,无法保证本博客所有内容的正确性。如有误导,请大家见谅,欢迎评论区指正!
    我创建了一个.NET开发交流群,用于分享学习心得和讨论相关技术难题。欢迎有兴趣的小伙伴扫码入群,相互学习!

  • 相关阅读:
    git ignore 添加忽略文件
    python| 闭包函数及装饰器
    python | DRF 框架知识总览
    python | CHROME底层原理和HTTP协议
    python| css 背景图片虚化效果
    python | js 图片与base64互相转换
    python | Linux各目录及每个目录的详细介绍
    python | 解决Django+Vue前后端分离的跨域问题及关闭csrf验证
    python | Nginx负载均衡策略
    python | Linux 搭建Nginx+uWSGI+Django环境
  • 原文地址:https://www.cnblogs.com/wml-it/p/14822252.html
Copyright © 2020-2023  润新知