如何在 C# 中编写条件锁?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/243152/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:33:23  来源:igfitidea点击:

How can I write a conditional lock in C#?

c#.netmultithreadinglocking

提问by sebagomez

The thing is I've been using the lock statementto protect a critical part of my code, but now, I realize I could allow concurrent execution of that critical code is some conditions are met.
Is there a way to condition the lock?

问题是我一直在使用lock 语句来保护我的代码的关键部分,但是现在,我意识到如果满足某些条件,我可以允许该关键代码的并发执行。
有没有办法调节锁?

采纳答案by Amy B

Action doThatThing = someMethod;

if (condition)
{
  lock(thatThing)
  {
     doThatThing();
  }
}
else
{
  doThatThing();
}

回答by noocyte

I'm guessing you've got some code that looks a little like this:

我猜你有一些看起来像这样的代码:

private Monkey GetScaryMonkey(int numberOfHeads){
    Monkey ape = null;        
    lock(this) {
        ape = new Monkey();
        ape.AddHeads(numberOfHeads);            
    }
    return ape;
}

To make this conditional couldn't you just do this:

为了使这个有条件,你不能这样做:

private Monkey GetScaryMonkey(int numberOfHeads){
    if ( numberOfHeads > 1 ) {
         lock(this) {
            return CreateNewMonkey( numberOfHeads );          
        }
    }
    return CreateNewMonkey( numberOfHeads );
}

Should work, no?

应该工作,不是吗?

回答by Tomalak

I think that question cries "race condition!". What if the condition turns from true to false shortly after the check, but before a thread enters the critical section of code? Or while a thread is in the process of executing it?

我认为这个问题叫“竞争条件!”。如果条件在检查后不久、但在线程进入代码的临界区之前从真变为假怎么办?或者当一个线程正在执行它的过程中?

回答by Marc Gravell

Actually, to avoid a race condition, I'd be tempted to use a ReaderWriterLockSlimhere - treat concurrent access as a read lock, and exclusive access as a write lock. That way, if the conditions change you won't end up with some inappropriate code still executing blindly in the region (under the false assumption that it is safe); a bit verbose, but (formatted for space):

实际上,为了避免竞争条件,我很想在ReaderWriterLockSlim此处使用- 将并发访问视为读锁,将排他访问视为写锁。这样,如果条件发生变化,您最终不会在该区域中盲目执行一些不适当的代码(假设它是安全的);有点冗长,但是(格式化为空格):

        if (someCondition) {
            lockObj.EnterReadLock();
            try { Foo(); }
            finally { lockObj.ExitReadLock(); }
        } else {
            lockObj.EnterWriteLock();
            try { Foo(); }
            finally { lockObj.ExitWriteLock(); }
        }

回答by marijne

bool locked = false;
if (condition) {
    Monitor.Enter(lockObject);
    locked = true;
}
try {
    // possibly critical section
}
finally {
    if (locked) Monitor.Exit(lockObject);
}

EDIT: yes, there is a race condition unless you can assure that the condition is constant while threads are entering.

编辑:是的,除非您可以确保在线程进入时条件保持不变,否则存在竞争条件。

回答by user31934

I'm no threading expert, but it sounds like you might be looking for something like this (double-checked locking). The idea is to check the condition both before and after acquiring the lock.

我不是线程专家,但听起来您可能正在寻找这样的东西(双重检查锁定)。这个想法是在获取锁之前和之后检查条件。

private static object lockHolder = new object();

if (ActionIsValid()) {
  lock(lockHolder) {
    if (ActionIsValid()) {
       DoSomething();    
    }
  }
}

回答by Pure.Krome

Use Double-checked locking pattern, as suggested above. that's the trick IMO :)

如上所述,使用双重检查锁定模式。这就是海事组织的诀窍:)

make sure you have your lock object as a static, as listed in not.that.dave.foley.myopenid.com's example.

确保您的锁对象为static,如 not.that.dave.foley.myopenid.com 的示例中所列。