我对静态类的静态成员的初始化有问题。据我所知,它只会被初始化一次,所以当我在并发中执行fooList.Add(...)时我会锁定这个变量,以确保这个操作是线程安全的:
internal static class ObjectA
{
private static object _lockAdd = new object();
public void functionA()
{
lock (_lockAdd)
{...
我遇到了一些奇怪的情况,所以我决定用log4net编写_lockAdd的哈希码,令我惊讶的是这就是我观察到的:
【信息】【2012-04-20 15:26:44,180】【主题12】 _lockAdd的哈希码(51755728)...
【信息】【2012-04-20 15:26:58,624】【thread16】 _lockAdd的哈希码(31071611)......
如您所见,两个'_lockAdd'地址不同,为什么会这样,或者我对静态成员的理解是错误的?当操作处于静态类时,我该如何确保线程安全?
抱歉假代码错误,这是我的实际代码:
internal static class UtilExtension
{
private static object _lockAdd = new object(); //initial twice ? why?
public static void DoAdd(this Type entityType)
{
if (!Pools.Has(entityType))
{
lock (_lockAdd)
{
if (!Pools.Has(entityType)) //insure operation below is thread safe
{
// i find something wrong in concurrency,so i log the _lockAdd's hashcode,
// and then i found it's hashcode is different( in my opinion, it means not the same variables )
LogUtil.Info(_lockAdd.GetHashCode().ToString());
//... do fooList.Add(...)
}
}
}
}
}
答案 0 :(得分:1)
对于仅用于lock
的对象,请使用readonly
:
private static readonly object _lockAdd = new object();
如果对象以某种方式被覆盖,那么下次启动应用程序时,很可能会从编译器或运行时获得不同的结果。
答案 1 :(得分:0)
也许我让它变得复杂,事实是,静态成员总是线程不安全。所以当我们使用静态成员(_lockAdd)作为锁定目标时,我们应该添加readonly以确保_lockAdd只启动一次。