How can I write a conditional lock in C#?

让人想犯罪 __ 提交于 2019-12-21 11:37:02

问题


The thing is I've been using the lock statement to 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?


回答1:


Action doThatThing = someMethod;

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



回答2:


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?




回答3:


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();    
    }
  }
}



回答4:


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.




回答5:


Actually, to avoid a race condition, I'd be tempted to use a ReaderWriterLockSlim here - 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):

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



回答6:


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.




回答7:


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?



来源:https://stackoverflow.com/questions/243152/how-can-i-write-a-conditional-lock-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!