5

我有一个可以从多个线程调用的方法,但我只想让第一个线程在方法内部执行一些逻辑。所以,我打算使用一个布尔变量。第一个进来的线程,会将布尔变量设置为 false(以防止更多线程进入),并执行方法逻辑。

使用此方法的后续线程将检查布尔变量。因为它被第一个线程设置为 false,所以它们将跳过方法逻辑。

在代码中,是这样的:

private void myMethod()
{
   if (firsTime)  //set to true in the constructor
   {
      firstTime = false; //To prevent other thread to come inside here.
      //method logic
   }
}

我想使用 lock 来执行此操作,但不确定将其放在哪里。

如果我锁定在“if”内部以将 firstTime 更改为 false,则可能有 2 个或更多线程已经进入 if(不想要这个)。

如果我在“if”之外锁定以将 firstTime 更改为 false,如果 firstTime 已经设置为 false,第一个线程如何进入 if 执行方法逻辑?

我的问题是:如何使锁具有所需的功能?(第一个线程设置布尔和执行方法逻辑)。

我无法锁定所有方法逻辑,因为这将是一个非常耗时的操作。

4

1 回答 1

7

你可以用它Interlocked.Exchange来解决这个问题。它将给定变量的值设置为指定的值并返回变量中的值,它会以原子方式完成所有操作。这样做将确保只有一个线程会运行以下代码if

private static int isFirst = 1;
public static void Foo()
{
    if (Interlocked.Exchange(ref isFirst, 0) == 1)
    {
        //DoStuff
    }
}

请注意,Interlocked.Exchange它没有采用 a 的重载bool,这就是为什么您不得不使用 a int(或其他类型)来代替,使用1for true 和0for false。

如果您想要使用lock, 而不是的解决方案Interlocked,您可以通过使用额外的本地bool值来实现:

private static bool isFirst = true;
private static object key = new object();
public static void Foo()
{
    bool amFirst;
    lock (key)
    {
        amFirst = isFirst;
        isFirst = false;
    }

    if (amFirst)
    {
        //DoStuff
    }
}
于 2013-08-09T16:12:16.413 回答