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?
应该工作,不是吗?