Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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_Multithreading_Pthreads_Mutex - Fatal编程技术网

C 在这种情况下我真的需要互斥锁吗?

C 在这种情况下我真的需要互斥锁吗?,c,multithreading,pthreads,mutex,C,Multithreading,Pthreads,Mutex,假设我们有三个线程,bool status\u flag[500]array,工作情况如下: 两个线程仅在不同索引处的状态标记数组中写入。而第三个线程只读取任何索引 所有三个线程都以不同的索引写入。而所有三个线程都在任何索引处读取 在写操作中,我们只是设置标志,不再重置它 status_flag [i] = true; 在阅读操作中,我们做了如下操作: for(;;){ //spinning to get flag true if(status_flag [i] ==

假设我们有三个线程,
bool status\u flag[500]
array,工作情况如下:

  • 两个线程仅在
    不同索引处的
    状态标记
    数组中写入。而第三个线程只读取任何索引

  • 所有三个线程都以不同的索引写入。而所有三个线程都在任何索引处读取

  • 在写操作中,我们只是设置标志,不再重置它

    status_flag [i] = true;
    
    在阅读操作中,我们做了如下操作:

        for(;;){  //spinning to get flag true
           if(status_flag [i] == true){
               //do_something ;
               break;
           }
        }
    
    如果编译器优化(分支预测)代码会发生什么


    我已经读了很多关于锁的书,但仍然对结论感到困惑。请帮我总结一下。

    如果所有线程都在不同的索引值上运行,那么您不需要锁。基本上,它相当于使用不同的变量。 在代码中,未设置或修改变量i的值。因此,它只读取标志的特定索引。对于写入,您使用的是不同的索引,在这种情况下,不需要使用lock。

    应用程序应确保一个以上的控制线程(线程或进程)对任何内存位置的访问受到限制,以便当另一个控制线程正在修改内存位置时,任何控制线程都不能读取或修改内存位置


    因此,如果不锁定,就不允许读取其他线程可能正在写入的内存。此外,POSIX的这一部分描述了哪个函数将同步线程之间的内存。在两个线程调用其中列出的任何函数之前,您无法保证一个线程所做的更改对另一个线程可见。

    您需要同步。是否需要互斥是另一个问题。是的,互斥/信号量,操作必须是“原子的”,因为您从另一个线程写入的位置读取。@mohan分支预测是处理器管道优化。如果您认为
    status\u flag
    将被优化掉,您可以使用
    volatile
    关键字。@JeremiahDicharry:请看…@mohan,它将失败,因为操作需要原子化。查看wikipedia页面-以了解可能发生的情况。显然,如果线程总是写入不同的索引而不是正在读取的索引,那么循环将是无限的…@Oliver Charlesworth我确保正在读取的索引一定会被写入。如果它在开始读取后在索引(如5)处读取,并在同一索引(如5)处写入。那个么,哪个线程的读数能够打破循环呢?或者它仍然会读取一个过时的数据。@Mohan:如果您在同一个索引上读写,那么您需要一个锁。@Dipanjan ok,我们不能避免在双线程读写情况下使用锁吗?@Mohan:这可以在没有锁的情况下工作,请尝试给予一些延迟或睡眠,以便控件也转到其他线程。可能会发生这样的情况:正在读取的线程得到了控制,它在无限循环中继续运行,而写入线程没有机会修改标志。我得到了它,但在出现标志时仍然感到困惑。如果我在没有同步的情况下读取值,我将得到一些垃圾或陈旧的数据。但若一个线程只写(true)标志,而另一个线程在for循环中读取,直到它变为true,那个该怎么办呢。没有同步就不能保证将更新的数据发送到其他线程吗?@Mohan:POSIX很清楚,不是吗?如果您不相信,请尝试不同步。你会失败,可能不总是,但有时会。@alk这不是关于相信。我只是想知道在其他阅读线索中,它在旋转以获得真正的标志,仍然有失败的机会为什么?可能是因为缓存或其他不允许读取线程以获取更新值的原因。我只想知道根本原因。@Mohan无法保证您会看到更改的值。在x86系统上,您通常会尽快看到该值,但也有一些情况是可以创建的(有意或无意),在使用正确的内存同步指令之前,更改的值永远不会传播到其他线程/CPU。POSIX是故意严格的,因为它可以移植到系统中,除非您同步,否则您永远看不到修改后的值。但即使在x86上,同步也可能会延迟很多。使用C11中的stdatomic.h所能做到的最低限度。@Mohan Btw。您打算如何处理该标志?该标志本身是无用的,因为读取该标志的其他线程可能看不到由该标志设置线程执行的其他内存写入。所以一个线程计算一些东西,在某处写下结果,设置结果完成的标志,主线程读取标志,看到它被设置,读取结果并获取未初始化的垃圾。这种情况经常发生。在过去10年中,x86 CPU的性能改进一直是关于CPU设计人员可以通过不同步的方式获得多少好处。