我可以安全地将常量值写入 C++ 中多个线程的变量吗?

Can I safely write a constant value to a variable from multiple threads in C++?

特别是,我想设置一个函数指针的值。为简单起见,我想从多个线程中多次执行此操作,但总是以这样的简单方式进行:

typedef void (*F)();
F f = 0;

void foo()
{
}

// called many times from multiple threads
void set()
{
    f = &foo;
}

int main()
{
    set();  // also other threads can invoke it at any time
    f();
    return 0;
}

因此,函数指针最初为NULL,然后在代码第一次执行时变为&foo。我想知道是否由于任何非原子写入操作,函数指针可能会中断。

保证设置后第一次读取

编辑:我澄清一下:

  1. 我使用函数指针的主要原因是为了消除模块之间的一些依赖关系。这是一个大的真实项目的一个小元素。实在是不能直接调用'foo'
  2. 我知道如何编程,我不需要有关互斥量之类的基本信息。我的问题是如果没有互斥体这是否安全。
  3. 代码中保证没有其他线程将指针设置为 &foo 以外的任何内容。

您是否考虑过使用 std::mutex and std::lock_guard 来加强线程安全?

例如

{
    std::lock_guard<std::mutex> lg(my_mutex);
    f = &foo;
    // then use f to perform your operation
}

在右大括号之后,lock_guard 超出范围并解锁您的 mutex。这意味着设置 f 的任何人都可以安全地使用该函数指针,因为知道另一个线程在设置它和尝试使用它之间没有更改函数指针。

我认为这更像是一个线程同步问题,而不是与 C++ 相关的问题。 您的问题的答案是,是的,您可以 在 C++ 中安全地向 varaible/pointer 写入一个值(不确定您所说的常量是什么意思;在我看来,您只是想分配一个函数指针),你只需要使用互斥这样线程就不会在你不希望它们覆盖时覆盖值

根据您最终想要实现的目标,您可能需要多个互斥体(即如果您想要确保线程分配函数指针的特定顺序),但这绝对是安全的方式它。

标准说您的代码会调用未定义的行为。但是在您的特定情况下,即使用您特定的编译器和体系结构,您的代码实际上可能没有问题。所以,从理论上讲,你的代码是不行的。从实际的角度来看,答案取决于您的具体情况,绝不是笼统的。个人建议将F f = 0;换成std::atomic<F> f(0);,这样保证代码在所有情况下都OK。

只是为了说明您的代码中断的情况:实现可能会选择在每次写入操作之前清除目标。这样的实现是合法的,符合标准,虽然不一定获奖:)