在C#.NET中查看函数的锁定部分

时间:2010-03-15 14:41:35

标签: asp.net caching

这段代码是否锁定了函数的一部分是正确的?或者,当多个会话同时要求同一个考试时,它是否会有使用缺点?

目的是首先要求考试的客户将组装它,所有下一个客户端都将获得缓存版本。

public Exam GetExamByExamDto(ExamDTO examDto, int languageId)
{
    Log.Warn("GetExamByExamDto");
    lock (LockString)
    {
        if (!ContainsExam(examDto.id, languageId))
        {
            Log.Warn("Assembling ExamDto");
            var examAssembler = new ExamAssembler();
            var exam = examAssembler.createExam(examDto);

            if (AddToCache(exam))
            {
                _examDictionary.Add(examDto.id + "_" + languageId, exam);
            }
            Log.Warn("Returning non cached ExamDto");
            return exam;
        }
    }
    Log.Warn("Returning cached ExamDto");
    return _examDictionary[examDto.id + "_" + languageId];
}

我觉得这不是办法。

4 个答案:

答案 0 :(得分:5)

永远不要锁定字符串 - 它们是不可变的并且是实体的,因此当尝试在其他地方访问相同的字符串时,最终可能会锁定整个应用程序。

只需使用新的object作为锁:

private readonly object Padlock = new object();

请参阅Tess Ferrandez撰写的this博文。

答案 1 :(得分:2)

LockString变量,它真的是一个字符串吗?你不应该锁定一个字符串,因为你可能会遇到与字符串实习有关的问题,这会导致多个锁被锁定。

另一件事是锁中似乎有很多代码,这意味着你锁定的时间比你需要的时间长。如果可以的话,尽量从锁中获取尽可能多的代码。

答案 2 :(得分:2)

它看起来基本没问题,但你不应该锁定string。实习使得很难控制哪个实例。只需创建一个单独的对象即可锁定:

 private object padLock = new object();

答案 3 :(得分:1)

你也可以使用双重检查(在考试缓存后,根本不会调用Monitor.Lock):

public Exam GetExamByExamDto(ExamDTO examDto, int languageId)
{
    Log.Warn("GetExamByExamDto");
    if (!ContainsExam(examDto.id, languageId))
    {
        lock (LockString) // Here should be some private locking object.
        {
            if (!ContainsExam(examDto.id, languageId))
            {
                Log.Warn("Assembling ExamDto");
                var examAssembler = new ExamAssembler();
                var exam = examAssembler.createExam(examDto);

                if (AddToCache(exam))
                {
                    _examDictionary.Add(examDto.id + "_" + languageId, exam);
                }
                Log.Warn("Returning non cached ExamDto");
                return exam;
            }
        }
        Log.Warn("Returning cached ExamDto");
        return _examDictionary[examDto.id + "_" + languageId];
    }
}