如何从另一个线程锁定方法的一部分?

时间:2014-12-18 13:35:08

标签: c# multithreading

如何从其他线程锁定c#中的方法的一部分? 我的意思是如果其中一个线程在这里,然后退出... 例如:

if(threads[0].WasHere)
{
   return;
}

3 个答案:

答案 0 :(得分:6)

一种有效的方式是互锁交换;通过在工作期间将一些令牌字段设置为非默认值,其他线程可以检查并退出。例如:

private int hazWorker; // = 0 - put this at the scope you want to protect

然后:

// means: atomically set hazWorker to 1, but only if the old value was 0, and
// tell me what the old value was (and compare that result to 0)
if(Interlocked.CompareExchange(ref hazWorker, 1, 0) != 0) {
    return; // someone else has the conch
}
try {
    // your work here
} finally {
    Interlocked.Exchange(ref hazWorker, 0); // set it back to default   
}

答案 1 :(得分:5)

您可以将Monitor.TryEnter用于此目的。

if(!Monitor.TryEnter(someLock))
{
   return;
}
try
{
    //Critical region
}
finally
{
    Monitor.Exit(someLock);
}

或者更可靠的方式与粗鲁线程中止(marc在评论中建议)

bool lockTaken = false;
try
{
    Monitor.TryEnter(someLock, ref lockTaken);
    if (lockTaken)
    {
        //Critical region
    }
}
finally
{
    if(lockTaken) Monitor.Exit(someLock);
}

请注意,这不会检查threads[0]是否仍然有效,而是检查是否有任何其他线程位于关键区域中。如果是这样,它将退出该方法。

答案 2 :(得分:2)

你可以使用bool值 - 分配它" false"默认情况下,然后第一个线程将其设置为" true"。然后这段代码看起来像这样:

if (!alreadyExecuted)
{
    // ...
    alreadyExecuted = true;
}

我还会把代码放在一个锁中,以确保只有一个线程在执行时(处理任何可能的竞争条件),如下所示。

lockVariable是一个更衣室变量,它可以是任何引用类型,例如。 object lockVariable = new object();

lock (lockVariable)
{
    if (!alreadyExecuted)
    {
        // ...
        alreadyExecuted = true;
    }
}