同步问题

本文关键字:问题 同步 | 更新日期: 2023-09-27 18:24:47

我的代码(C#.NET 4)中有以下场景:

我有一个初始化为false的布尔变量:

bool b = false;

现在我正在实例化线程的数量,每个线程都需要读取b的值。第一个读取b-的线程应该将其值更改为true(并执行一些逻辑…),而其他线程则不应该执行任何操作。在读取"b"的值时,我需要对其使用同步机制吗?还是只能在将其值设置为true时锁定它?这应该能提高我的表现,但我想知道它是否安全。。

同步问题

所以要求是:

  • 多个线程读取单个bool变量
  • 如果线程看到false值,它应该将其更改为true并执行额外的工作
  • 如果线程看到true值,则不应该发生其他任何事情
  • 应该只有一个线程能够更改值并执行额外的工作

所以代码看起来像:

public class Example
{
  private bool b = false;
  public void DoSomething()
  {
    if (!b)
    {
      b = true;
      DoExtraStuff();
    }
  }
}

当然,如果有多个线程执行DoSomething,并且意图是DoExtraStuff应该只执行一次,那么这是不安全的。问题是线程将在b的读写上竞争。

您确实需要使对b的读写成为原子。这可以使用lock关键字来完成。

public class Example
{
  private bool b = false;
  private object locker = new object();
  public void DoSomething()
  {
    bool trigger = false;
    lock (locker)
    {
      if (!b)
      {
        b = true;
        trigger = true;
      }
    }
    if (trigger)
    {
      DoExtraStuff();
    }
  }
}

存在经由Interlocked.CompareExhange使用CAS操作的替代模式。不幸的是,没有接受bool的重载,但如果您愿意将该bool更改为int,则以下操作也适用。

public class Example
{
  private int b = 0;
  public void DoSomething()
  {
    if (Interlocked.CompareExchange(ref b, 0, 1) == 0)
    {
      DoExtraStuff();
    }
  }
}