冲突锁定两个方法,以便只有1个线程可以使用锁

时间:2010-06-25 13:31:31

标签: c# multithreading locking

我遇到有关多线程并将项目插入字典的问题。当insertbin主题具有重复的id时,我会遇到以下情况:

    private static readonly Timer bufferChecker;
    private static readonly List<SubjectStartRulePair> inBuffer;
    private static readonly IDictionary<Guid, Subject> beingProcessed;
    private static readonly object objLock;

    static InBuffer()
    {
        objLock = new object();
        inBuffer = new List<SubjectStartRulePair>();
        beingProcessed = new Dictionary<Guid, Subject>();
        bufferChecker = new Timer(x => ProcessThreads(), null, 1000, 1000);
    }

    public static void ProcessThreads()
    {
        lock(objLock)
        {
            var bufferedItems = inBuffer.OrderBy(x => x.QueuedTime);
            foreach (var item in bufferedItems)
            {
                if (!beingProcessed.ContainsKey(item.Subject.SubjectId)) //Important check which validates if there is already a Thread running
                {
                    var thread = new Thread(
                        x =>
                        {
                            //Thread #2 is here and runs into duplicate Key
                            beingProcessed.Add(item.Subject.SubjectId, item.Subject); 
                            item.StartRule(item.Subject);
                            beingProcessed.Remove(item.Subject.SubjectId);
                        });

                    thread.Start();
                    inBuffer.Remove(item);
                }
            }
        }
    }

    public static void TryToExecute(Subject subject, IBusinessRule rule)
    {
        lock (objLock)
        {
            if (beingProcessed.ContainsKey(subject.SubjectId)) //Important check which validates if there is already a Thread running
            {
                inBuffer.Add(
                    new SubjectStartRulePair
                        {
                            QueuedTime = DateTime.Now,
                            Subject = subject,
                            StartRule = (x =>
                            {
                                rule.RunChildren(subject);
                                return true;
                            })
                        }
                );
            }
            else
            {
                var thread = new Thread(
                    x =>
                    {
                        beingProcessed.Add(subject.SubjectId, subject);
                        rule.RunChildren(subject);
                        beingProcessed.Remove(subject.SubjectId);
                    });

                thread.Start(); //Thread #1 is here
            }
        }
    }

我已经锁定了两种方法,但锁似乎不起作用......似乎两个线程都在不同的方法上进入锁。我错过了使用lock()的意义吗?有关如何正确实现这一点的任何想法?重要的注意事项是,Timer(bufferChecker)每秒调用ProcessThreads()方法。

1 个答案:

答案 0 :(得分:2)

您正在每个方法中启动一个新线程 - 这些新线程将不会拥有(或请求)该锁。

因此虽然ProcessThreadsTryToExecute中只有一个可以有效地运行,但是您无法控制lambda表达式中的位。如果那些也需要相互排斥,你需要在这些lambdas中加上lock语句。