测试互斥锁之外的值:内存排序问题

J T*_*ler 4 c pthreads

我正在尝试减少代码需要执行的锁定量,并且遇到了一些关于pthread_mutex_lock如何处理其内存障碍的学术问题.为了使这个易于理解,假设互斥锁正在保护一个初始化后完全静态的数据字段,但我想将此设置推迟到第一次访问时.我想写的代码如下:

/* assume the code safely sets data to null at setup,
 * and the mutex is correctly setup 
 */
if (NULL == data) {
    pthread_mutex_lock(&lock);
    /* Need to re-check data in case it was already setup */
    if (NULL == data) 
        data = deferred_setup_fcn();
    pthread_mutex_unlock(&lock);
}
Run Code Online (Sandbox Code Playgroud)

我看到的可能问题是数据是在锁内设置的,但是在锁外读取.编译器是否可以跨互斥锁定调用缓存数据值?或者我是否必须插入适当的volatile关键字以防止这种情况发生?

我知道用pthread_once调用可以做到这一点,但我想避免使用另一个数据字段(锁已经存在保护相关字段).

指向POSIX线程函数调用内存排序的权威指南的指针也可以很好地工作.

caf*_*caf 5

这种模式的问题在于内存障碍在两个线程之间,但是示例中的读者可能不执行任何暗示障碍的指令.

因此,deferred_setup_fcn()即使写入data是可见的(从与作者竞争的阅读器的角度),也不能保证所执行的存储器写入是可见的.也就是说,读者可以看到data != NULL,但当它实际上试图访问指向的值时data,找到半初始化或未初始化的结构.