Конфликт при блокировке двумя способами, так что только 1 поток может использовать блокировку - PullRequest
1 голос
/ 25 июня 2010

У меня проблема с многопоточностью и вставкой элемента в словарь.Следующая ситуация - это то, что я приветствую, когда вставляю объекты с дублирующими идентификаторами:

    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 ()?Любая идея о том, как я должен реализовать это правильно?Важное замечание: метод ProcessThreads () вызывается Timer (bufferChecker) каждую секунду.

1 Ответ

2 голосов
/ 25 июня 2010

Вы запускаете новый поток в каждом методе - эти новые потоки не будут иметь (или не будут запрашивать) блокировку.

Таким образом, хотя только один из ProcessThreads или TryToExecute может эффективно выполняться одновременно, вы не можете контролировать биты в лямбда-выражениях. Если они также требуют взаимного исключения, вы должны поместить в эти лямбды выражение lock.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...