C# Note26: [MethodImpl(MethodImplOptions.Synchronized)]与lock机制
在进行.NET开发时,经常会遇见如何保持线程同步的情况。在众多的线程同步的可选方式中,加锁无疑是最为常用的。如果仅仅是基于方法级别的线程同步,使用System.Runtime.CompilerServices.MethodImplAttribute无疑是最为简洁的一种方式。MethodImplAttribute可以用于instance method,也可以用于static method。当在某个方法上标注了MethodImplAttribute,并指定MethodImplOptions.Synchronized参数,可以确保在不同线程中运行的该方式以同步的方式运行。
查阅MSDN的说明:
The method can be executed by only one thread at a time. Static methods lock on the type, whereas instance methods lock on the instance. Only one thread can execute in any of the instance functions, and only one thread can execute in any of a class's static functions. 这个方法一次只能执行一个线程。静态方法锁定类型,而实例方法锁定实例。只有一个线程可以在任何一个实例函数中执行,而且只有一个线程可以在任何一个类的静态函数中执行。
可以看出:
- [MethodImplAttribute(MethodImplOptions.Synchronized)]仍然是采用加锁的机制实现线程的同步。
- 如果它被应用到instance method,相当于对当前实例加锁。
- 如果它被应用到static method,相当于当前类型加锁
可参考文章:
[MethodImpl(MethodImplOptions.Synchronized)]、lock(this)与lock(typeof(...))
- lock机制
关键字lock的作用是锁定某一代码块,让同一时间只有一个线程访问该代码块。
lock(X)
{
//需要锁定的代码....
}
那么为什么上面这段话能够锁定代码?其中的奥妙就是X这个对象,事实上X是任意一种引用类型,它在这儿起的作用就是任何线程执行到lock(X)时候,X需要独享才能运行下面的代码,若假定现在有3个线程A,B,C都执行到了lock(X)而ABC因为此时都占有X,这时ABC就要停下来排个队,一个一个使用X,从而起到在下面的代码块内只有一个线程在运行(因为此时只有一个线程独享X,其余两个在排队),所以这个X必须是所有要执行临界区域代码进程必须共有的一个资源,从而起到抑制线程的作用。
lock最需要注意的一个问题就是线程死锁,MSDN上列出了3个典型问题:
通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:
- 如果实例可以被公共访问,将出现 lock (this) 问题。
- 如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。
- 由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。
最佳做法是定义 private 对象来锁定, 或 private shared 对象变量来保护所有实例所共有的数据。
- lock的内涵(Monitor类)
另外,使用lock来实现C#线程同步,在C#编译器编译lock语句时,将其编译成了调用Monitor类。一条lock语句会被编译成调用Monitor的Enter和Exit方法。Monitor在 System.Threading命名空中。lock的功能就相当于直接调用Monitor的Entry方法,所不同的是,lock方法在结束后,会自动解除锁定,当然,在IL中是调用了Monitor的Exit方法,但在C#程序中,看起来是自动解锁的,这类似于C#中的using语句,可以自动释放数据库等资源。但如果直接在C#源程序中使用Monitor类,就必须调用Exit方法来显式地解除锁定。
示例:
Monitor.Enter(lockObj);
try
{
// 代码
}
catch(Exception e)
{
// 异常处理代码
}
finally
{
Monitor.Exit(lockObj); // 解除锁定
}
Exit方法最后在finally里调用,这样无论在方法在发生异常、返回还是正常执行,都会执行到finally,并调用Exit方法解除锁定。
Monitor类不仅可以完全取代lock语句,还可以使用TryEntry方法设置一个锁定超时。
示例:
if(Monitor.TryEntry(lockObj, 1000))
{
try
{
}
finally
{
Monitor.Exit(lockObj);
}
}
else
{
// 超时后的处理代码
}
设置锁定超时时间为1秒,即在1秒中后,lockObj还未被解锁,TryEntry方法就会返回false,如果在1秒之内,lockObj被解锁,TryEntry返回true。这种方法对于避免死锁提供了一种不错的思路。
C# Note26: [MethodImpl(MethodImplOptions.Synchronized)]与lock机制的更多相关文章
- [MethodImpl(MethodImplOptions.Synchronized)]与lock机制
[MethodImpl(MethodImplOptions.Synchronized)]与lock机制 在进行.NET开发时,经常会遇见如何保持线程同步的情况.在众多的线程同步的可选方式中,加锁无疑是 ...
- [MethodImpl(MethodImplOptions.Synchronized)]、lock(this)与lock(typeof(...))
对于稍微有点经验的.NET开发人员来说,倘若被问及如何保持线程同步,我想很多人都能说好好几种.在众多的线程同步的可选方式中,加锁无疑是最为常用的.如果仅仅是基于方法级别的线程同步,使用System.R ...
- [MethodImpl(MethodImplOptions.Synchronized)]
在NopCommerce项目的Nop.Core类库中有一个EngineContext类中有一个Initialize方法用到了[MethodImpl(MethodImplOptions.Synchron ...
- C#方法同步 [MethodImpl(MethodImplOptions.Synchronized)]
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- MethodImplOptions.Synchronized的一点讨论
Review代码发现有一个方法加了[MethodImpl(MethodImplOptions.Synchronized)] 属性,这个属性的目的,从名字上就可以看出,是要对所有线程进行同步执行. 对方 ...
- Synchronized和lock的区别和用法
一.synchronized和lock的用法区别 (1)synchronized(隐式锁):在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要 ...
- synchronized 与 lock 的区别
synchronized 和 lock 的用法区别 synchronized(隐式锁):在需要同步的对象中加入此控制,synchronized 可以加在方法上,也可以加在特定代码块中,括号中表示需要锁 ...
- 转:synchronized和LOCK的实现原理---深入JVM锁机制
JVM底层又是如何实现synchronized的? 目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug ...
- java 锁机制(synchronized 与 Lock)
在java中,解决同步问题,很多时候都会使用到synchronized和Lock,这两者都是在多线程并发时候常使用的锁机制. synchronized是java中的一个关键字,也就是说是java内置的 ...
随机推荐
- [NOI2017]蔬菜
[NOI2017]蔬菜 题目描述 大意就是有\(n\)种物品,第\(i\)个物品有\(c_i\)个,单价是\(a_i\).然后每天你可以卖出最多\(m\)个物品.每天结束后第\(i\)种物品会减少\( ...
- 2.04-proxy-handler
import urllib.request def create_proxy_handler(): url = "https://blog.csdn.net/m0_37499059/arti ...
- SpringBoot实战之SpringBoot自动配置原理
SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...
- UVA10570-Meeting with Aliens(枚举)
Problem UVA1616-Caravan Robbers Accept: 531 Submit: 2490Time Limit: 3000 mSec Problem Description I ...
- PHP与Nginx之间的运行机制以及原理
一.普及Nginx与Php-fpm相关知识点 Nginx是什么 Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服 ...
- mysql执行顺序
SELECT语句执行顺序 SELECT语句中子句的执行顺序与SELECT语句中子句的输入顺序是不一样的,所以并不是从SELECT子句开始执行的,而是按照下面的顺序执行: 开始->FROM子句-& ...
- PHP小接
一种是innodb,一种是myisam,两者的主要区别是①myisam不支持事务处理,而innoDB支持事务处理 ②myisam 不支持外键,innoDB支持外键 ③myisam支持全文检索,而inn ...
- 【移动端】单位em相关资料
https://www.cnblogs.com/koubazhuanshu/p/6985331.html https://www.w3cplus.com/css/px-to-em 不建议使用 作者:s ...
- Consul在.Net Core中初体验
Consul在.Net Core中初体验 简介 在阅读本文前我想您应该对微服务架构有一个基本的或者模糊的了解 Consul是一个服务管理软件,它其实有很多组件,包括服务发现配置共享键值对存储等 本文主 ...
- CF980E The Number Games
CF980E The Number Games 给定一棵大小为 \(n\) 的树,第 \(i\) 个点的点权为 \(2^i\) ,删掉 \(k\) 个点及其连边,使得剩下的点组成一个连通块,且权值和最 ...