C - 可以通过不同的线程修改全局指针吗?

OfL*_*ers 5 c multithreading pointers

全局指针在线程之间是否存在范围?

例如,假设我有两个文件,file1.c和file2.c:

file1.c中:

uint64_t *g_ptr = NULL;

modify_ptr(&g_ptr) { 
    //code to modify g_ptr to point to a valid address 
}

read_from_addr() {
    //code which uses g_ptr to read values from the memory it's pointing to
}
Run Code Online (Sandbox Code Playgroud)

file2.c中:

function2A() {
    read_from_addr();
}
Run Code Online (Sandbox Code Playgroud)

所以我有threadA,它运行在file1.c中并执行modify_ptr(&g_ptr)和read_from_addr().然后threadB运行,它通过执行function2A()的file2.c运行.

我的问题是:threadB是否看到g_ptr被修改了?或者它仍然看到它指向NULL?

如果不是这样,那么指针是全局的意味着什么?如何确保在不同线程之间可以访问此指针?

如果我需要澄清任何事情,请告诉我.谢谢

Ada*_*eld 7

我的问题是:threadB是否看到g_ptr被修改了?或者它仍然看到它指向NULL?

也许.如果在没有任何外部同步的情况下访问,您可能会看到奇怪的,高度不可重现的结果 - 在某些情况下,编译器可能会根据对代码的分析进行某些优化,这可能源于假设变量是在某些代码路径中未修改.例如,考虑以下代码:

// Global variable
int global = 0;

// Thread 1 runs this code:
while (global == 0)
{
    // Do nothing
}

// Thread 2 at some point does this:
global = 1;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,编译器可以看到globalwhile循环内部没有被修改,并且它不调用任何外部函数,因此它可以将其"优化"为如下所示:

if (global == 0)
{
    while (1)
    {
        // Do nothing
    }
}
Run Code Online (Sandbox Code Playgroud)

volatile关键字添加到变量的声明中会阻止编译器进行此优化,但这不是volatileC语言标准化时的预期用例.在volatile这里添加只会以较小的方式减慢程序速度并掩盖真正的问题 - 缺乏正确的同步.

管理需要从多个线程同时访问的全局变量的正确方法是使用互斥锁来保护它们1.例如,这是modify_ptr使用POSIX线程互斥锁的简单实现:

uint64_t *g_ptr = NULL;
pthread_mutex_t g_ptr_mutex = PTHREAD_MUTEX_INITIALIZER;

void modify_ptr(uint64_t **ptr, pthread_mutex_t *mutex)
{
    // Lock the mutex, assign the pointer to a new value, then unlock the mutex
    pthread_mutex_lock(mutex);
    *ptr = ...;
    pthread_mutex_unlock(mutex);
}

void read_from_addr()
{
    modify_ptr(&g_ptr, &g_ptr_mutex);
}
Run Code Online (Sandbox Code Playgroud)

互斥函数确保插入适当的内存屏障,因此对由互斥锁保护的变量所做的任何更改都将正确传播到其他CPU内核,前提是变量的每次访问(包括读取!)都受互斥锁保护.

1)您也可以使用专门的无锁数据结构,但这些是一种先进的技术,很容易出错

  • +1很好的答案,谢谢你希望安静使用volatile-for-thread-synchro ideologues(至少现在,无论如何). (3认同)