C# 将锁定以防止通过反射进行更改
假设一个类C# 将锁定以防止通过反射进行更改,c#,reflection,locking,C#,Reflection,Locking,假设一个类SomeClass带有private static字段,如下所示。使用lock同步访问此字段 private static SomeClass _instance private static object _sync = new object(); public static SomeClass Instance { get { lock (_sync) { if (_instance == null)
SomeClass
带有private static
字段,如下所示。使用lock
同步访问此字段
private static SomeClass _instance
private static object _sync = new object();
public static SomeClass Instance
{
get
{
lock (_sync)
{
if (_instance == null)
{
_instance = Create();
}
return _instance;
}
}
}
当来自不同线程的另一个代码尝试使用反射将此变量的值设置为例如null
时,lock
是否会阻止此操作,并让反射调用等待直到释放锁
例如,类似这样的事情:
Type type = typeof(SomeClass);
string fieldName = "_instance";
object value = null;
FieldInfo field = type.GetField(fieldName, true);
field.SetValue(null, value);
不,锁定不会阻止任何不通过锁定同一资源的访问。由于反射不会通过
锁定
,因此您将获得竞争条件。
以下是我的意思(与您的代码略有不同,但不是做同样的事情)→
void SetOne(){
lock (_sync){
critical_element = SOME_VALUE;
}
}
void SetTwo(){
critical_element = SOME_ANOTHER_VALUE;
}
以上绝对有比赛条件
以下是我对OP问题的理解。我认为OP想要使用单例模式,这里是一个非常好的线程安全实现。您也不需要处理锁。但是,一些不好的用户可能仍然使用反射设置支持字段
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton(){}
}
公共密封类单例
{
private static readonly Lazy Lazy=new Lazy(()=>new Singleton());
公共静态单例实例{get{return lazy.Value;}}
私有单例(){}
}
这里的答案很简单:这不是一个社会工程问题——抓住代码评审中的不良行为。我认为这个问题至少应该得到一个解释“为什么?”的答案,这是与CLR相关的技术原因。文档中只说,“避免使用以下对象作为锁对象:类型实例,因为这些实例可能由typeof
操作符或反射获取”,而OP并不是这样做的。lock
是协作的。访问相同受保护资源的所有代码都必须按照您试图建立的任何锁定规则编写。如果其他人编写的代码访问受保护的资源,但不遵循您的锁定约定,则没有什么可以阻止这一点。你怎么想象其他任何东西会知道,特别是\u sync
和\u instance
是相关的?@dee-这与反射无关。如果您在此类中编写了另一个方法,该方法访问相同的资源,但未能使用相同的锁对象,那么该方法也可以正常编译和运行,并与相同的问题竞争谢谢您的回答!我知道锁只对通过正常访问的调用有效,但是通过反射,值会直接改变。这是我的问题,我不确定锁是如何工作的。懒惰的单身汉很酷,谢谢。