我可以在此ManualResetEvent中使用锁来确保线程安全吗? [英] Can I use a lock with this ManualResetEvent to ensure thread safety?
问题描述
假设我有两个用于操作计数的函数,以及一个以固定间隔触发的OnTimer函数。
Say I have two functions that manipulate a count, and an OnTimer function that fires at a regular interval.
void IncrementCount()
{
_myCount++;
}
void OverwriteCount(int newValue)
{
_myCount = newValue;
}
void OnTimer()
{
Console.WriteLine(_myCount);
}
我的愿望是,如果/当调用OverwriteCount时,IncrementCount不能为
My desire is that if/when OverwriteCount is called, IncrementCount can't be executed until the timer function executes.
我解决此问题的最初想法是使用ManualResetEvent来帮助同步行为:
My initial thought to resolve this was to use a ManualResetEvent to help synchronize behaviors:
private static ManualResetEventSlim mre = new ManualResetEventSlim(initialState: true);
void IncrementCount()
{
mre.Wait(-1); // can't increment until the event is signaled
_myCount++;
}
void OverwriteCount(int newValue)
{
mre.Reset(); // unsignal the event, blocking threads
_myCount = newValue;
}
void OnTimer()
{
Console.WriteLine(_myCount);
mre.Set(); // signal the event
}
我关心的是退化的多线程方案,其中线程A超过了IncrementCount()中的mre.Wait(),但实际上尚未增加_myCount。然后,线程B调用mre.Reset()并覆盖_myCount。线程A然后转弯并递增_myCount。
My concern is a degenerate, multi-threaded scenario where thread A gets past the mre.Wait() in IncrementCount() but hasn't actually incremented _myCount yet. Thread B then calls mre.Reset() and overwrites _myCount. Thread A then gets a turn and increments _myCount.
我可以通过在IncrementCount()和OverwriteCount()内添加锁以确保只有一个线程可以修改_myCount来解决此问题一次?如果我在握住锁的同时等待复位事件而陷入僵局,会不会招致死锁?
Could I solve this by also adding a lock inside IncrementCount() and OverwriteCount() to ensure only one thread can modify _myCount at a time? Do I risk deadlock if I get stuck waiting on the reset event while holding the lock?
推荐答案
如果我了解您,那么可以如果您选择合适的锁定方式,它将可以正常工作。可能有更细粒度的方法,但是到目前为止,我仍然没有发现任何
If i understand you, then yes it would work if you chose what to lock appropriately. There is probably a more granular way to do this, but as of now i see nothing wrong with this
void IncrementCount()
{
mre.Wait();
// lets not cause a race, lock until OverwriteCount is finished
lock (_sync)
{
_myCount++;
}
}
void OverwriteCount(int newValue)
{
// lock this so we can assure the count is updated
lock (_sync)
{
mre.Reset(); // unsignal the event, blocking threads
_myCount = newValue;
}
}
void OnTimer()
{
Console.WriteLine(_myCount);
mre.Set(); // signal the event
}
这篇关于我可以在此ManualResetEvent中使用锁来确保线程安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!