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

时间:2022-10-11 14:53:44

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?

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

7 个解决方案

#1


5  

Action doThatThing = someMethod;

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

#2


9  

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?

我认为这个问题会叫“竞争条件!”。如果在检查后不久条件从true变为false,但在线程进入代码的关键部分之前怎么办?或者一个线程正在执行它?

#3


8  

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


7  

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


4  

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):

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

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

#6


2  

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

如上所述,使用双重检查锁定模式。这是IMO的诀窍:)

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

确保你的锁对象是静态的,如not.that.dave.foley.myopenid.com的例子中所列。

#7


1  

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?

应该工作,不是吗?

#1


5  

Action doThatThing = someMethod;

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

#2


9  

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?

我认为这个问题会叫“竞争条件!”。如果在检查后不久条件从true变为false,但在线程进入代码的关键部分之前怎么办?或者一个线程正在执行它?

#3


8  

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


7  

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


4  

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):

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

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

#6


2  

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

如上所述,使用双重检查锁定模式。这是IMO的诀窍:)

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

确保你的锁对象是静态的,如not.that.dave.foley.myopenid.com的例子中所列。

#7


1  

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?

应该工作,不是吗?