C#线程系列讲座(5):同步技术之Monitor

简介:
在上一讲介绍了使用 lock 来实现线程之间的同步。实际上,这个 lock C# 的一个障眼法,在 C# 编译器编译 lock 语句时,将其编译成了调用 Monitor 类。先看看下面的 C# 源代码:
public   static   void  MyLock()
{
    
lock  ( typeof (Program))
    {
    }
}

     上面的代码通过lock 语句使MyLock 同步,这个方法被编译成IL 后,代码如图1 所示。
 
从上图被标注的区域可以看到,一条lock语句被编译成了调用MonitorEnterExit方法。MonitorSystem.Threading命名空间中。lock的功能就相当于直接调用MonitorEntry方法,所不同的是,lock方法在结束后,会自动解除锁定,当然,在IL中是调用了MonitorExit方法,但在C#程序中,看起来是自动解锁的,这类似于C#中的using语句,可以自动释放数据库等的资源。但如果直接在C#源程序中使用Monitor类,就必须调用Exit方法来显式地解除锁定。如下面的代码所示:

Monitor.Entry(lockObj);
try
{
    
//  lockObj的同布区
}
catch (Exception e)
{
    
//  异常处理代码
}
finally
{
    Monitor.Exit(lockObj);  
//  解除锁定
}

    Exit 方法最后在finally 里调用,这样无论在方法在发生异常、返回还是正常执行,都会执行到finally ,并调用Exit 方法解除锁定。
    Monitor 类不仅可以完全取代lock 语句(如果只使用lock 语句本身的功能,最好还是直接用lock 语句吧),还可以使用TryEntry 方法设置一个锁定超时,单位是毫秒。如下面的代码所示:
if (Monitor.TryEntry(lockObj,  1000 ))
{
    
try
    {
    }
    
finally
    {
        Monitor.Exit(lockObj);
    }
}
else
{
    
//  超时后的处理代码
}
     上面的代码设置了锁定超时时间为1 秒,也就是说,在1 秒中后,lockObj 还未被解锁,TryEntry 方法就会返回false ,如果在1 秒之内,lockObj 被解锁,TryEntry 返回true 。我们可以使用这种方法来避免死锁,如下面的代码所示:

     class  Program
    {
        
private   static  Object objA  =   new  Object();
        
private   static  Object objB  =   new  Object();
        
public   static   void  LockA()
        {
            
if  (Monitor.TryEnter(objA,  1000 ))
            {
                Thread.Sleep(
1000 );
                
if  (Monitor.TryEnter(objB,  2000 ))
                {
                    Monitor.Exit(objB);
                }
                
else
                {

                    Console.WriteLine(
" LockB timeout " );
                }
                Monitor.Exit(objA);
            }
            Console.WriteLine(
" LockA " );
        }
        
public   static   void  LockB()
        {
            
if  (Monitor.TryEnter(objB,  2000 ))
            {
                Thread.Sleep(
2000 );
                
if  (Monitor.TryEnter(objA,  1000 ))
                {
                    Monitor.Exit(objA);
                }
                
else
                {
                    Console.WriteLine(
" LockA timeout " );
                }
                Monitor.Exit(objB);
            }
            Console.WriteLine(
" LockB " );
        }
        
public   static   void  Main()
        {
            Thread threadA 
=   new  Thread(LockA);
            Thread threadB 
=   new  Thread(LockB);
            threadA.Start();
            threadB.Start();
            Thread.Sleep(
4000 );         
            Console.WriteLine(
" 线程结束 " );
        }
    }
     上面的代码是在上一讲举的死锁的例子,但在这一讲将lock 语句改成了TryEntry 方法,而且设置了锁定超时间,由于在等待一定时间后,不管被锁定的对象是否被解锁,TryEntry 方法都会返回,因此,上面的代码是不会死锁的。运行上面的代码的结果如图2 所示。
 
 如果TryEntry方法的超时时间为System.Threading.Timeout.InfiniteTryEntry方法就相当于Entry方法,如果超时时间为0,不管是否解锁,TryEntry方法都会立即返回。




 本文转自 androidguy 51CTO博客,原文链接:http://blog.51cto.com/androidguy/216660,如需转载请自行联系原作者


相关文章
|
24天前
|
缓存 监控 算法
基于 C# 网络套接字算法的局域网实时监控技术探究
在数字化办公与网络安全需求增长的背景下,局域网实时监控成为企业管理和安全防护的关键。本文介绍C#网络套接字算法在局域网实时监控中的应用,涵盖套接字创建、绑定监听、连接建立和数据传输等操作,并通过代码示例展示其实现方式。服务端和客户端通过套接字进行屏幕截图等数据的实时传输,保障网络稳定与信息安全。同时,文章探讨了算法的优缺点及优化方向,如异步编程、数据压缩与缓存、错误处理与重传机制,以提升系统性能。
39 2
|
2月前
|
Web App开发 Linux C#
C# 网页截图全攻略:三种技术与 Chrome 路径查找指南
本文主要介绍了在 C# 中实现网页截图的几种技术及相关要点。涵盖了 PuppeteerSharp、Selenium 和 HtmlToImage 三种方式,分别阐述了它们的安装步骤及核心代码。同时,针对在 C# 中寻找 Windows 上 chrome.exe 路径这一问题,分析了未安装 Google Chrome 和已安装两种情况下的查找原因,并给出了相关参考链接,还列举了一系列与 C# 使用 Selenium、获取 chrome.exe 路径以及在 Linux 上部署相关的参考资料。
109 11
|
3月前
|
开发框架 算法 .NET
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
|
3月前
|
开发框架 Cloud Native .NET
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
|
3月前
|
程序员 C# 数据库
C# 比较对象新思路,利用反射技术打造更灵活的比较工具
中途接手的项目,碰到需要在更新对象信息时比较并记录差异的需求,最变态的还有附加要求,怎么办?有没有既能满足需求又能对项目影响最小的方法呢?分享这个我封装的方法,一个利用反射技术打造的更灵活的比较工具
|
4月前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
4月前
|
人工智能 开发框架 前端开发
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
|
5月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
107 1
|
4月前
|
人工智能 开发框架 安全
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)
|
5月前
|
人工智能 开发框架 Cloud Native
C#/.NET/.NET Core技术前沿周刊 | 第 9 期(2024年10.07-10.13)
C#/.NET/.NET Core技术前沿周刊 | 第 9 期(2024年10.07-10.13)

相关实验场景

更多