C# 同步问题

C# 同步问题,c#,.net,multithreading,synchronization,C#,.net,Multithreading,Synchronization,我的代码(C#.NET 4)中有以下场景: 我有一个初始化为false的布尔变量: bool b = false; 现在我正在实例化线程的数量,每个线程都需要读取b的值。第一个读取b-的线程应该将其值更改为true(并执行一些逻辑…),而其他线程不应该执行任何操作。读取“b”的值时是否需要使用同步机制,或者只能在将其值设置为true时锁定它? 这将提高我的性能,但我想知道它是否安全。因此要求如下: 多个线程读取单个bool变量 如果线程看到一个false值,它应该将其更改为true,并执行额

我的代码(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();
    }
  }
}
有一种备用模式,使用通过
联锁的操作。CompareExhange
。不幸的是,没有接受
bool
的重载,但是如果您愿意将
bool
更改为
int
,以下操作也可以

public class Example
{
  private int b = 0;

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

因此,要求如下:

  • 多个线程读取单个
    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();
    }
  }
}
有一种备用模式,使用通过
联锁的操作。CompareExhange
。不幸的是,没有接受
bool
的重载,但是如果您愿意将
bool
更改为
int
,以下操作也可以

public class Example
{
  private int b = 0;

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

你是对的。多个线程可能会看到'!b'为true,将输入if-block。是的,您是对的,这是正确的版本。希望OP会出现并更改已接受的答案,以便我可以删除我的答案。我似乎误解了他想做什么。@Tudor:是的,误解的问题经常发生在我身上。这个问题的措辞本可以再好一点,你是对的。多个线程可能会看到'!b'为true,将输入if-block。是的,您是对的,这是正确的版本。希望OP会出现并更改已接受的答案,以便我可以删除我的答案。我似乎误解了他想做什么。@Tudor:是的,误解的问题经常发生在我身上。这个问题的措辞本可以再好一点。