C#使用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 + "\t");
                }
                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 + "\t");
                    }
                    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()方法在尝试获取一个对象上的显式锁。

到此这篇关于C#使用Monitor类实现线程同步的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#多线程的ResetAbort()方法

    一.简介 Abort方法可以通过跑出ThreadAbortException异常中止线程,而使用ResetAbort方法可以取消中止线程的操作,下面通过代码演示使用 ResetAbort方法. 二.代码 class Program { static void Main(string[] args) { Thread thread = new Thread(ThreadMethod); //执行的必须是无返回值的方法 thread.Name = "子線程A"; thread.Start(

  • C# 如何获取当前进程或线程的ID

    目录 获取当前进程或线程的ID C# 进程读取方法 获取当前进程或线程的ID 如果获得当前进程的Id用: Process[] processes = Process.GetProcesses();  foreach(Process process in processes)  {  if(process.ProcessName == "进程名"  {  MessageBox.Show(process.Id);  }  } Process processes   =Process.Get

  • 关于C#线程的全面解析

    目录 线程的作用和意义 线程生命周期 C#创建线程 C#让线程休眠一会 C#销毁线程 C#线程优先级 lock:给线程加锁,保证线程同步 Monitor:锁定资源 Mutex:互斥锁 线程的作用和意义 线程 被定义为程序的执行路径.每个线程都定义了一个独特的控制流.如果您的应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作. 线程是轻量级进程.一个使用线程的常见实例是现代操作系统中并行编程的实现.使用线程节省了 CPU 周期的浪费,同时提高了应用程序

  • C#使用LOCK实现线程同步

    一.简介 线程安全概念:线程安全是指在当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据污染. 线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等.当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团.线程同步的真实意思和字面意思恰好相反.线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操

  • C#多线程的Join()方法

    一.简介 Join方法主要是用来阻塞调用线程,直到某个线程终止或经过了指定时间为止.官方的解释比较乏味,通俗的说就是创建一个子线程,给它加了这个方法,其它线程就会暂停执行,直到这个线程执行完为止才去执行(包括主线程). 二.代码 class Program { static void Main(string[] args) { Thread threadA = new Thread(ThreadMethod); threadA.Name = "線程A"; Thread threadB

  • C#使用ThreadPriority设置线程优先级

    一.简介 如果在应用程序中有多个线程在运行,但一些线程比另一些线程重要,这种情况下可以在一个进程中为不同的线程指定不同的优先级.线程的优先级可以通过Thread类Priority属性设置,Priority属性是一个ThreadPriority型枚举,列举了5个优先等级:AboveNormal.BelowNormal.Highest.Lowest.Normal.公共语言运行库默认是Normal类型的. 二.代码 class Program { static void Main(string[] a

  • C#使用Monitor类实现线程同步

    一.简介 Lock关键字是Monitor的一种替换用法,lock在IL代码中会被翻译成Monitor. lock (obj) { //代码段 } //就等同于 Monitor.Enter(obj); //代码段 Monitor.Exit(obj); Monitor的常用属性和方法: Enter(Object) 在指定对象上获取排他锁. Exit(Object) 释放指定对象上的排他锁. Pulse 通知等待队列中的线程锁定对象状态的更改. PulseAll 通知所有的等待线程对象状态的更改. T

  • Java Atomic类及线程同步新机制原理解析

    一.为什么要使用Atomic类? 看一下下面这个小程序,模拟计数,创建10个线程,共同访问这个int count = 0 :每个线程给count往上加10000,这个时候你需要加锁,如果不加锁会出现线程安全问题,但是使用AtomicInteger之后就不用再做加锁的操作了,因为AtomicInteger内部使用了CAS操作,直接无锁往上递增,有人会问问什么会出现无锁操作,答案只有一个:那就是快呗: 下面是AtomicInteger的使用方法: package com.example.demo.t

  • C#线程同步的几种方法总结

    我们在编程的时候,有时会使用多线程来解决问题,比如你的程序需要在后台处理一大堆数据,但还要使用户界面处于可操作状态:或者你的程序需要访问一些外部资源如数据库或网络文件等.这些情况你都可以创建一个子线程去处理,然而,多线程不可避免地会带来一个问题,就是线程同步的问题.如果这个问题处理不好,我们就会得到一些非预期的结果. 在网上也看过一些关于线程同步的文章,其实线程同步有好几种方法,下面我就简单的做一下归纳. 一.volatile关键字 volatile是最简单的一种同步方法,当然简单是要付出代价的

  • ruby线程实现生产者消费者问题示例(队列Queue实现线程同步)

    Ruby线程实现经典的生产者消费者问题,用ruby中的Queue类实现线程同步问题. 复制代码 代码如下: require "thread"  puts "ProAndCon" queue = Queue.new    #用队列Queue实现线程同步 producer = Thread.new do      10.times do |i|          sleep rand(i) # 让线程睡眠一段时间          queue << i   

  • 详解Java编程中线程同步以及定时启动线程的方法

    使用wait()与notify()实现线程间协作 1. wait()与notify()/notifyAll() 调用sleep()和yield()的时候锁并没有被释放,而调用wait()将释放锁.这样另一个任务(线程)可以获得当前对象的锁,从而进入它的synchronized方法中.可以通过notify()/notifyAll(),或者时间到期,从wait()中恢复执行. 只能在同步控制方法或同步块中调用wait().notify()和notifyAll().如果在非同步的方法里调用这些方法,在

  • c#线程同步使用详解示例

    在应用程序中使用多个线程的一个好处是每个线程都可以异步执行.对于 Windows 应用程序,耗时的任务可以在后台执行,而使应用程序窗口和控件保持响应.对于服务器应用程序,多线程处理提供了用不同线程处理每个传入请求的能力.否则,在完全满足前一个请求之前,将无法处理每个新请求.然而,线程的异步特性意味着必须协调对资源(如文件句柄.网络连接和内存)的访问.否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作. 线程同步的方式 线程同步有:临界区.互斥区.事件.信号量四种

  • c#.net多线程编程教学——线程同步

    随着对多线程学习的深入,你可能觉得需要了解一些有关线程共享资源的问题. .NET framework提供了很多的类和数据类型来控制对共享资源的访问. 考虑一种我们经常遇到的情况:有一些全局变量和共享的类变量,我们需要从不同的线程来更新它们,可以通过使用System.Threading.Interlocked类完成这样的任务,它提供了原子的,非模块化的整数更新操作. 还有你可以使用System.Threading.Monitor类锁定对象的方法的一段代码,使其暂时不能被别的线程访问. System

  • .net中线程同步的典型场景和问题剖析

    在使用多线程进行编程时,有一些经典的线程同步问题,对于这些问题,.net提供了多种不同的类来解决.除了要考虑场景本身,一个重要的问题是,这些线程是否在同一个应用程序域中运行.如果线程都在同一应用程序域中运行,则可以使用一些所谓"轻量"级的同步类,否则要使用另一些类,而这些类都是对操作系统所提供的同步原语的包装,相对来说更消耗资源.我在这儿介绍一些典型的应用场景和相关的问题. 多线程争用独占资源 常常有一些资源线程独占的,如果有多个线程同时需要访问这要的资源,就形成了一个争用问题.这类资

  • 详解C#多线程之线程同步

    多线程内容大致分两部分,其一是异步操作,可通过专用,线程池,Task,Parallel,PLINQ等,而这里又涉及工作线程与IO线程:其二是线程同步问题,鄙人现在学习与探究的是线程同步问题. 通过学习<CLR via C#>里面的内容,对线程同步形成了脉络较清晰的体系结构,在多线程中实现线程同步的是线程同步构造,这个构造分两大类,一个是基元构造,一个是混合构造.所谓基元则是在代码中使用最简单的构造.基原构造又分成两类,一个是用户模式,另一个是内核模式.而混合构造则是在内部会使用基元构造的用户模

  • C#中线程同步对象的方法分析

    本文实例讲述了C#中线程同步对象的方法.分享给大家供大家参考.具体分析如下: 在编写多线程程序时无可避免会遇到线程的同步问题.什么是线程的同步呢? 举个例子:如果在一个公司里面有一个变量记录某人T的工资count=100,有两个主管A和B(即工作线程)在早一些时候拿了这个变量的值回去,过了一段时间A主管将T的工资加了5块,并存回count变量,而B主管将T的工资减去3块,并存回count变量.好了,本来T君可以得到102块的工资的,现在就变成98块了.这就是线程同步要解决的问题. 在.Net的某

随机推荐