繁体   English   中英

我需要记忆障碍吗?

[英]Do I need a memory barrier?

在下面的C99示例中,是否保证在读取或写入缓冲区后设置buffer_full标志(即使启用了-O2优化)? 还是我需要一个内存屏障来确保正确的顺序?

我希望这可以在对齐的32位读写是原子的系统上运行。

假设每个线程仅运行一个实例,并且没有其他线程在访问bufferbuffer_full

char buffer[100];
int buffer_full;

// write interesting data to the buffer. does not read.
void fill_buffer(char* buffer, size_t buffsz);
// read the interesting data in the buffer. does not write.
void use_buffer(const char* buffer, size_t buffsz);

void writer_thread()
{
    if (!buffer_full) {
        fill_buffer(buffer, sizeof(buffer));
        // is a memory barrier needed here?
        buffer_full = 1;
    }
}

void reader_thread()
{
    if (buffer_full) {
        use_buffer(buffer, sizeof(buffer));
        // is a memory barrier needed here?
        buffer_full = 0;
    }
}

我认为您是在问编译器是否可以通过调用fill_buffer()read_buffer() fill_buffer() buffer_full的分配重新排序。 仅当这种优化(和任何优化)不会改变程序的外部可观察行为时,才允许这样做。

在这种情况下,由于buffer_full具有外部链接,因此编译器不太可能对是否允许优化抱有信心。 这可能是能够做到这一点,如果的定义fill_buffer()use_buffer()函数,和每一个他们自己称之为功能 writer_thread()reader_thread()函数位于同一翻译单元中,但这在某种程度上取决于它们的实现。 如果合格的编译器不确定是否允许优化,则它一定不能执行。

由于您的命名暗示这两个函数将在不同的线程中运行,但是,如果没有诸如内存屏障之类的同步操作,您将无法确定一个线程将感知到对共享,非_Atomic ,非-由其他线程执行的volatile数据。

此外,如果一个线程写入一个非原子变量,而另一个线程访问该相同变量(读或写),则将存在数据争用,除非在每个可能的总体操作顺序中,在两者之间进行了同步操作或原子操作。 volatile变量在这里并没有真正帮助(请参阅为什么volatile在多线程C或C ++编程中不被认为有用 )。 但是,如果使buffer_full原子,或者使用对其进行原子读和写操作来实现函数,则这将避免数据竞争,不仅涉及该变量,还涉及buffer (对于您当前的代码结构)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM