Monitor里边有一些static方法,可以用于在对象上获取同步锁,来进行一些进程同步控制操作

用法及注意点如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace myTest
{
class Program
{
// 一个比较容易犯的错误
// 使用 Monitor 锁定对象(即引用类型)而不是值类型。将值类型变量传递给 Enter 时,
//它被装箱为对象。如果再次将相同的变量传递给 Enter,则它被装箱为一个单独对象,而且线程不会阻止。Monitor
//本应保护的代码未受保护。此外,将变量传递给 Exit 时,
//也创建了另一个单独对象。因为传递给 Exit 的对象和传递给 Enter 的对象不同,Monitor
//将引发 SynchronizationLockException
//这种情况最好用 Interlocked 来完成
private static int _num = ;
// 装箱一下就可以了
private static object num = _num;
static void Main(string[] args)
{ Thread t1 = new Thread(new ThreadStart(addNum));
t1.Name = "线程1";
Thread t2 = new Thread(new ThreadStart(addNum));
t2.Name = "线程2";
t1.Start();
t2.Start();
Console.ReadLine();
}
//|- 拥有锁的线程 lockObj->|- 就绪队列(ready queue) |- 等待队列(wait queue)
// 就绪队列:尝试lock对象的线程
// 等待队列:在等待中, !!!不会主动!!! 去lock对象的线程 Monitor.wait 会使线程进入等待队列
// 如果只调用wait不调用pulse,可能使线程进入死锁
// 下面执行的时间线: t1获得锁——t1打印——2000ms——t1Pulse(此时无线程在等待队列,故无效)——2000ms——t1释放锁并进入等待队列——
// t2获得锁——t2打印——2000ms——t2Pulse(此时t1线程在等待队列,t1进入就绪队列)——2000ms——t2释放锁并进入等待队列——
// t1获得锁——t1Pulse(此时t2线程在等待队列,t2进入就绪队列)——t1打印——t1释放锁——t1退出——
// t2获得锁——t2Pulse(此时无线程在等待队列,故无效)——t2打印——t2释放锁——t2退出
private static void addNum()
{
Boolean gotLock = false;
try
{
// Monitor.Enter(num); //获取排它锁
Monitor.Enter(num, ref gotLock);
Console.WriteLine(Thread.CurrentThread.Name+ DateTime.Now.ToString() + "——————" + num);
//释放锁并让线程进入等待队列,直到它重新获得锁
Thread.Sleep();
//通知等待的线程进入就绪队列,有锁了
Monitor.Pulse(num);
Thread.Sleep();
Monitor.Wait(num);
Monitor.Pulse(num);
}
finally
{
Console.WriteLine(Thread.CurrentThread.Name + DateTime.Now.ToString() + "——————" + num);
if (gotLock)
{
Monitor.Exit(num);
}
}
}
}
}

运行结果:

用Monitor类获得对象锁的try .. catch finally的过程还有一个语法糖,lock关键字

C# 对象锁——Monitor的更多相关文章

  1. C# 对象锁

    现在有一种场景,服务端将一个任务派发给10个客户端执行,所有客户端执行完后,整个任务才算执行完. 每个客户端执行完后,通过http发送一个完成的消息给服务端,服务端发送邮件通知给用户. 当10个客户端 ...

  2. 命名空间System.Threading命名空间的同步锁 Monitor类

    官方备注: Monitor类通过向单个线程授予对象所来控制对对象的访问.对象所提供限制访问代码块的能力.当一个线程拥有对象的锁时,其他任何线程都不能获取该锁.还可以使用Monitor来确保不会允许其他 ...

  3. Thread锁 Monitor类、Lock关键字和Mutex类

    Monitor 类锁定一个对象 当多线程公用一个对象时,也会出现和公用代码类似的问题,这种问题就不应该使用lock关键字了,这里需要用到System.Threading中的一个类Monitor,我们可 ...

  4. 一张图讲解对象锁和关键字synchronized修饰方法

    每个对象在出生的时候就有一把钥匙(监视器),那么被synchronized 修饰的方法相当于给方法加了一个锁,这个方法就可以进行同步,在多线程的时候,不会出现线程安全问题. 下面通过一张图片进行讲解: ...

  5. synchronized同步对象锁

    package com.system.util; import com.common.Constants; import com.util.Cache; /** * 创建同步对象锁 * * @auth ...

  6. java synchronized类锁,对象锁详解(转载)

    觉得还不错 留个记录,转载自http://zhh9106.iteye.com/blog/2151791 在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看 ...

  7. java 哪些情况下会使对象锁释放

    Java_多线程_锁释放 问:Java多线程运行环境中,在哪些情况下会使对象锁释放?答:由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的 ...

  8. 多线程并发 synchronized对象锁的控制与优化

    本文针对用户取款时多线程并发情境,进行相关多线程控制与优化的描述. 首先建立用户类UserTest.业务操作类SynchronizedTest.数据存取类DataStore,多线程测试类MultiTh ...

  9. Java:使用synchronized和Lock对象获取对象锁

    在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制. 1.对象的锁 所有对象都自动含有单一的锁. JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数变为0.在任务(线程)第一次给对象加锁 ...

随机推荐

  1. centos中docker mongodb 配置

    安装docker,对于Centos7,如下: $ sudo yum update$ sudo yum -y install docker$ sudo systemctl start docker 首先 ...

  2. 安卓(android)之实现断点下载功能

    一.建立实体类 1.文件实体类 package com.example.zjw.myapplication.dao; import java.io.Serializable; /** * 预下载文件实 ...

  3. HashMap实现缓存(二)

    package com.cache; import java.util.*; //Description: 管理缓存 //可扩展的功能:当chche到内存溢出时必须清除掉最早期的一些缓存对象,这就要求 ...

  4. errno

    关于errno有以下需要注意: 1  A common mistake is to do if (somecall() == -1) {                printf("som ...

  5. 信号量sem

    一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更 ...

  6. 使用THINKPHP中的控制器和模块查询数据库

    1,自定义一个UserController的控制器,导入tp的控制器与模块执行相应的操作. ----var_dump()方法是判断一个变量的类型与长度,并输出变量的数值,如果变量有值输的是变量的值. ...

  7. dnslog注入

    使用Powershell反弹Meterpreter Shell cloudeye在windows下的应用 今天突发奇想的一个姿势,算不上什么技巧,分享一下吧. 看到有人问过.http://zone.w ...

  8. Powershell 十个常见任务

    学习Powershell的时候,基本的语法也了解了一些,但是就是不知道要写些什么?作为一个过来者,和大家一起分享下常见的几个管理任务脚本. 1.更改本地Administrator账号密码 [ADSI] ...

  9. c = (a / b, a%b) 运算输出顺序

    #include<iostream> int main() { using namespace std; int a, b, c; a = ; b = ; c = ; printf(&qu ...

  10. 安卓中級教程(11):深入研究餓了麼的各個java檔運作關係(1)

    package com.example.ele_me.activity; import android.annotation.SuppressLint; import android.app.Acti ...