我遇到有关多线程并将项目插入字典的问题。当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()方法。
答案 0 :(得分:2)
您正在每个方法中启动一个新线程 - 这些新线程将不会拥有(或请求)该锁。
因此虽然ProcessThreads
或TryToExecute
中只有一个可以有效地运行,但是您无法控制lambda表达式中的位。如果那些也需要相互排斥,你需要在这些lambdas中加上lock
语句。