lock无限等待,Monitor.TryEnter可设超时;前者自动释放锁,后者需手动配对Exit并用lockTaken防护;Monitor支持Wait/Pulse实现条件等待,lock不支持。

lock 会一直等,Monitor.TryEnter 可设超时
这是最直接的区别:当你用 lock(obj),线程一旦抢不到锁,就会**无限阻塞**,直到前一个持有者释放;而 Monitor.TryEnter(obj, timeout) 允许你指定最多等多久(毫秒),超时就返回 false,不卡死。
- 适合对响应时间敏感的场景,比如 UI 线程、实时服务接口,不能因锁被长期占用而挂起
-
timeout = 0表示“只试一次”,立即返回成功或失败,常用于非阻塞轮询 -
timeout = -1等价于无限等待 —— 此时行为接近lock,但依然要手动配对Exit,没lock安全
lock 自动保底,Monitor.TryEnter 必须自己写 finally 释放
lock 是语法糖,编译后自动包成 try-finally,哪怕临界区抛异常,锁也一定释放;Monitor.TryEnter 不带这种保障 —— 如果你忘了在 finally 里调用 Monitor.Exit,或者只在 if 分支里调了,就可能造成死锁。
- 正确写法必须是:
bool lockTaken = false; try { if (Monitor.TryEnter(obj, 1000)) lockTaken = true; /* 临界区 */ } finally { if (lockTaken) Monitor.Exit(obj); } - 漏掉
lockTaken判断?Monitor.Exit会抛SynchronizationLockException - 把
Monitor.Exit写在if里而不是finally?异常一出,锁就永远拿不回来了
Monitor.TryEnter 能配合 Wait/Pulse 实现复杂同步,lock 不行
如果你需要做生产者-消费者、信号量式唤醒、条件等待(比如“等队列不为空再取”),就必须用 Monitor.Wait 和 Monitor.Pulse —— 这些方法只能在已持有 Monitor 锁的前提下调用,而 lock 语法不暴露锁状态,也没法中途释放再等待。
2013年07月06日 V1.60 升级包更新方式:admin文件夹改成你后台目录名,然后补丁包里的所有文件覆盖进去。1.[新增]后台引导页加入非IE浏览器提示,后台部分功能在非IE浏览器下可能没法使用2.[改进]淘客商品管理 首页 列表页 内容页 的下拉项加入颜色来区别不同项3.[改进]后台新增/修改淘客商品,增加淘宝字样的图标和天猫字样图标改成天猫logo图标4.[改进]为统一名称,“分类”改
-
Monitor.Wait(obj)会**自动释放锁 + 挂起当前线程**,等别人Pulse后重新争锁 - 这个“释放锁→等待→重获锁”的原子过程,
lock无法表达 - 所以涉及线程协作逻辑时,哪怕只是加个超时,也得切到
Monitor.Enter/TryEnter + Wait/Pulse全套流程
锁对象安全要求一样,但 Monitor 更容易误用
两者都要求锁对象是私有、引用类型、不可变(推荐 private readonly object _sync = new object(););但 Monitor 因为方法多、路径长,更容易踩坑:
- 对同一个对象反复
Enter但Exit次数不够?锁不会真正释放 - 在没持锁时调
Monitor.Wait或Monitor.Pulse?直接抛SynchronizationLockException - 用字符串字面量或
this当锁对象?跨实例/跨程序集意外共享,引发隐蔽竞争 -
Monitor.IsEntered(obj)是调试用的,**不能用来代替 TryEnter 做锁检查**(它不保证原子性)
简单场景无脑用 lock;只要出现“等太久不行”“我要等某个条件”“我得通知别人”,就得切到 Monitor,并且每一步都要对齐 Enter/Exit、Wait/Pulse 的契约 —— 少一个 finally,就少一分确定性。









