将锁定防止通过反射完成的更改
Will lock prevent changes done via reflection
假设一个 class 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);
不,锁定不会阻止任何未通过锁定同一资源的访问。由于反射不会通过 lock
,您将获得竞争条件。
这是(与您的代码略有不同,但仍然做同样的事情)我的意思→
void SetOne(){
lock (_sync){
critical_element = SOME_VALUE;
}
}
void SetTwo(){
critical_element = SOME_ANOTHER_VALUE;
}
上面肯定有竞争条件。
这是我对 OP 问题的理解。我认为 OP 想要使用 Singleton
模式,这是一个非常好的线程安全实现。您也不需要处理锁。但是,一些不良用户可能仍会使用反射设置支持字段。
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(){}
}
假设一个 class 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);
不,锁定不会阻止任何未通过锁定同一资源的访问。由于反射不会通过 lock
,您将获得竞争条件。
这是(与您的代码略有不同,但仍然做同样的事情)我的意思→
void SetOne(){
lock (_sync){
critical_element = SOME_VALUE;
}
}
void SetTwo(){
critical_element = SOME_ANOTHER_VALUE;
}
上面肯定有竞争条件。
这是我对 OP 问题的理解。我认为 OP 想要使用 Singleton
模式,这是一个非常好的线程安全实现。您也不需要处理锁。但是,一些不良用户可能仍会使用反射设置支持字段。
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(){}
}