Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 这足以检测比赛情况吗?_C_Linux_Gcc - Fatal编程技术网

C 这足以检测比赛情况吗?

C 这足以检测比赛情况吗?,c,linux,gcc,C,Linux,Gcc,假设我有一个多线程应用程序,我使用相同的输入运行它。它是否足以检测每个加载和存储以检测写入和写入读取数据竞争?我的意思是,从记录的加载和存储地址来看,如果我们可以看到哪个线程加载了哪个线程,哪个线程存储了哪个线程,那么我们可以通过注意重叠的地址来检测写读写数据竞争。还是我遗漏了什么 还是我遗漏了什么 你错过了很多。正如普比所说,如果你看到读,然后在T1中写,然后读,然后在T2中写,你就不能说没有种族了。你需要知道有关锁的情况 你可能想使用一个工具,比如谷歌的 更新: 但我的方法会覆盖所有比赛还是

假设我有一个多线程应用程序,我使用相同的输入运行它。它是否足以检测每个加载和存储以检测写入和写入读取数据竞争?我的意思是,从记录的加载和存储地址来看,如果我们可以看到哪个线程加载了哪个线程,哪个线程存储了哪个线程,那么我们可以通过注意重叠的地址来检测写读写数据竞争。还是我遗漏了什么

还是我遗漏了什么

你错过了很多。正如普比所说,如果你看到读,然后在T1中写,然后读,然后在T2中写,你就不能说没有种族了。你需要知道有关锁的情况

你可能想使用一个工具,比如谷歌的

更新:

但我的方法会覆盖所有比赛还是至少部分比赛

你在这里和其他答案上的评论似乎表明你不明白什么是种族

你的方法可能会暴露一些种族,是的。它保证不会覆盖其中的大部分(这将使练习徒劳无益)

还是我遗漏了什么

你错过了很多。正如普比所说,如果你看到读,然后在T1中写,然后读,然后在T2中写,你就不能说没有种族了。你需要知道有关锁的情况

你可能想使用一个工具,比如谷歌的

更新:

但我的方法会覆盖所有比赛还是至少部分比赛

你在这里和其他答案上的评论似乎表明你不明白什么是种族


你的方法可能会暴露一些种族,是的。它保证不会覆盖大多数线程(这将使练习无效)。

您将学到的最明显的一点是,有多个线程使用相同的内存。这本身并不一定不好

良好的用途包括信号量保护、原子访问和RCU或双缓冲等机制

不良使用包括种族条件、真实和错误共享:

  • 竞争条件主要源于排序问题——如果某个任务a在其执行结束时写入某些内容,而任务B在其开始时需要该值,则最好确保B的读取仅在a完成后发生。信号量、信号或类似的东西是一个很好的解决方案。当然,也可以在同一个线程中运行它
  • 真正的共享意味着两个或多个内核正在积极地读写相同的内存地址。这会降低处理器的速度,因为它将不断地向其他内核(当然还有内存)的缓存发送任何更改。您的方法可以抓住这一点,但可能不会突出它
  • 假共享甚至比真共享更复杂:处理器缓存不在单个字节上工作,而是在“缓存线”上工作——缓存线包含多个值。如果core A继续敲打一行的字节0,而core B继续写入字节4,则缓存更新仍将使整个处理器暂停

    • 您将了解到的最明显的事情是,有多个线程使用相同的内存。这本身并不一定不好

      良好的用途包括信号量保护、原子访问和RCU或双缓冲等机制

      不良使用包括种族条件、真实和错误共享:

      • 竞争条件主要源于排序问题——如果某个任务a在其执行结束时写入某些内容,而任务B在其开始时需要该值,则最好确保B的读取仅在a完成后发生。信号量、信号或类似的东西是一个很好的解决方案。当然,也可以在同一个线程中运行它
      • 真正的共享意味着两个或多个内核正在积极地读写相同的内存地址。这会降低处理器的速度,因为它将不断地向其他内核(当然还有内存)的缓存发送任何更改。您的方法可以抓住这一点,但可能不会突出它
      • 假共享甚至比真共享更复杂:处理器缓存不在单个字节上工作,而是在“缓存线”上工作——缓存线包含多个值。如果core A继续敲打一行的字节0,而core B继续写入字节4,则缓存更新仍将使整个处理器暂停

        • 以下是一个来自维基百科的简单示例,我对其稍加修改:

          作为一个简单的例子,让我们假设两个线程T1和T2各自需要 对一个全局整数的值执行算术运算。理想情况下 将进行以下操作顺序:

        • 整数i=0;(内存)
        • T1将i的值从内存读入寄存器1:0
        • T1增加寄存器1中i的值:(寄存器1内容)+1=1
        • T1将寄存器1的值存储在内存中:1
        • T2将i的值从内存读入寄存器2:1
        • T2乘以寄存器2中i的值:(寄存器2内容)*2=2
        • T2将寄存器2的值存储在内存中:2
        • 整数i=2;(内存)
        • 在上面所示的情况下,i的最终值是2,正如预期的那样。 但是,如果两个线程同时运行而未锁定或 同步时,操作的结果可能是错误的。这个 下面的备选操作顺序演示了此场景:

        • 整数i=0;(内存)
        • T1将i的值从内存读入寄存器1:0
        • T2将i的值从内存读入寄存器2:0
        • T1增加寄存器1中i的值:(寄存器1内容)+1=1
        • T2乘以寄存器2中i的值:(寄存器2内容)*2=0
        • T1将寄存器1的值存储在内存中:1
        • T2将寄存器2的值存储在内存中:0
        • 整数i=0;(内存)
        • i的最终值为0,而不是预期的结果2。这 由于增量op