【问题标题】:multithreading - increment integer in one thread and decrease in another thread多线程 - 在一个线程中增加整数并在另一个线程中减少
【发布时间】:2012-08-21 12:08:51
【问题描述】:

在一个多线程程序中,有 2 个线程 - 线程 1 - 将运行一个循环,将整数变量增加 1000 倍,然后退出 线程 2 - 将运行一个循环,将整数变量减少 1000 次然后退出

两个线程都在一个信号量上等待并大致同时启动,并被安排在大致相同的时间在不同的内核上运行。

两个线程退出后,整型变量的值会为零吗? 注意:不使用锁定(互斥锁等)

让我们假设 linux 和 x86 架构以及多核硬件。

如果将相同的整数声明为 volatile (C++) 会发生什么情况?

【问题讨论】:

  • 答案是否定的,值不一定为零,除非你使用原子整数。
  • 无锁定 - 这是否意味着递增/递减操作不是原子的?如果是这样,则不能保证最终的零值。
  • @Rost..操作是纯整数递增/递减让我们说 ++i 和 --i
  • @Medicine 这意味着结果不能保证为零。

标签: c++ linux multithreading locking multicore


【解决方案1】:

如果多个线程同时修改同一个内存位置,则程序会发生数据争用并且影响未定义。结果几乎可以是任何东西,假设你得到了一个结果。对于像整数类型这样的简单变量,原子将消除数据竞争并提供适当的同步。使用atomic_int(也称为atomic<int>)。

【讨论】:

    【解决方案2】:

    无论是否可变,您都不能期望任何特定的输出(范围 [-1000,1000] 除外)——即使是单个并发写入也可能破坏递增/递减的结果(即使在 CPU 上也不是原子的)级别)。

    【讨论】:

    • "两个线程在一个信号量上等待并同时启动......" 这是不可能的,在给定的时间内只会启动一个线程,而另一个线程将在一个信号量上等待。在你的情况下;如果 Thread1 首先开始运行,那么它将将该值增加 1000 倍,例如从 0 到 1000,然后 Thread2 开始运行,该值减少 1000 倍,因此该值将为 0。考虑,如果线程 2 先启动,则该值将变为-1000,然后在 Thread1 结束时该值为 0。
    • 如果您只允许其中一个在特定时间运行,那么输出当然会是 0。但如果它们同时运行,我的回答适用。
    • @Viswesn 机器上有 2 个内核,信号量值被外部进程提高到 2,导致两个线程的 sem_wait 成功......所以两个线程将大约在同一时间安排....如果 1000 次迭代太小,可以说有一百万次迭代,而不是每个线程相应地递增和递减
    • @Medicine 感谢您指定它正在计数信号量。
    【解决方案3】:

    您将需要使用适当的原子,并可能使用完整的内存屏障。

    volatile 在这种情况下不会为您做任何事情(足够好,您可以使用)。

    【讨论】:

      【解决方案4】:

      整数读/写可能是原子的,也可能不是原子的。所以答案是否定的,结果不一定是 0。

      【讨论】:

        【解决方案5】:

        递增和递减需要三个操作:从内存中取值,修改,写回内存。在大多数平台上,不能保证这三个操作都以原子方式执行,除非您使用 C++11 原子类型、编译器特定(或程序集)原子内在函数或锁特别请求它。

        volatile与线程同步无关;它只是确保内存访问实际发生并且相对于同一线程中的其他副作用正确排序。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多