函数
GetYYY()
是从 ASP.NET 基页调用的。因此,多个用户可以同时发生这种情况。 _data
应该只初始化一次。但是,该锁不会锁定静态列表。从我们的日志中,log.Debug
执行了两次并记录了 2 个值(请参阅下面的评论)。为什么锁不起作用?
public class XXX
{
private static List<YYY> _data = new List<YYY>();
public List<YYY> GetYYY()
{
lock (_data)
{
if (_data.Count > 0)
{
return _data;
}
_data = new List<YYY>();
try
{
var query = @" SELECT ...";
using (var dab = GetDataAccessBlock())
{
OracleDataReader reader = dab.ExecuteSQLAsReader(query);
while (reader.Read())
{
_data.Add(new YYY
{
P1 = reader["P1"].ToString(),
P2 = ...
});
}
log.Debug(_data.Count + " values are returned. this should be called only once when app restarts"); //this logs twice with wrong numbers 863 and 787... when there is only one user, it should be 432
}
}
catch (Exception ex)
{
log.Error("..." );
}
return _data;
}
}
}
必须对一个对象进行锁定,该对象的生命周期要长于您要保护的数据。
您所采用的锁位于一个within
GetYYY()
可变的对象上,因此没有保证,并且因此肯定是一个错误。正如评论中所表达的,锁定其他东西。锁定该调用范围之外的内容,并在调用期间持续存在。
虽然不是最好的方法,但您仍然可以锁定列表,但前提是您创建它一次,并更改您的语义在调用中以在添加之前清除列表。这样,您的列表在通话中仍然存在,但其内容可以更改。
也就是说......最好使用类范围的外部锁作为机制。