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

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

本文关键字:C++ 变量 线程 是否 安全 常量      更新时间:2023-10-16

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

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::mutexstd::lock_guard 来强制实施线程安全?

例如

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

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

该标准说你的代码调用未定义的行为。但是在你的特定情况下,即使用你的特定编译器和架构,你的代码实际上可能是没有问题的。因此,从理论的角度来看,您的代码是不行的。从实际的角度来看,答案取决于您的具体情况,绝不是一般性的。就个人而言,我建议用std::atomic<F> f(0);替换F f = 0;,以便保证代码在所有情况下都没问题。

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

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

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