【问题标题】:Conflict on Locking two methods so that only 1 Thread can use the lock锁定两种方法的冲突,以便只有 1 个线程可以使用锁
【发布时间】:2010-06-25 13:31:30
【问题描述】:

我有一个关于多线程和将项目插入字典的问题。以下情况是我在插入具有重复 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() 方法。

【问题讨论】:

    标签: c# multithreading locking


    【解决方案1】:

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

    因此,虽然ProcessThreadsTryToExecute 一次只能有效运行一个,但您无法控制 lambda 表达式中的位。如果这些也需要互斥,则需要在这些 lambda 中添加 lock 语句。

    【讨论】:

    • 感谢乔恩的快速遮阳篷!我将 beingProcessed.Add() 移到 lambda 之外以解决此问题,这也给出了预期的结果:]
    猜你喜欢
    • 2014-10-29
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多