【问题标题】:Is it safe to use different bytes of an int64 from different thread?使用来自不同线程的不同字节的 int64 是否安全?
【发布时间】:2020-07-16 06:40:04
【问题描述】:

例如,有 8 个线程使用 uint64 作为共享内存,并在该区域使用不同的字节(无锁)。

一个线程只能访问某个字节,所以不存在字节争用。

在这种情况下,安全吗?而且从性能的角度来看,使用CAS来操作整个整数而不是每个字节更好吗?

【问题讨论】:

  • C++ 按对象的顺序处理线程安全,而不是“内存中的字节”。如果多个线程正在访问同一个对象,那么就会存在数据竞争,即使它们使用屏蔽来仅访问“不同的字节”。请提供minimal reproducible example,以便我们查看您的操作是否安全。
  • 请出示minimal reproducible example,答案可能是否定的,这不安全
  • 魔鬼在我耳边低语:“union”。
  • 角度向我尖叫:“don't use unions for type punning
  • 我可以推荐一本书“concurrency in action”,它非常详细地解释了这一点。

标签: c++ multithreading


【解决方案1】:

不,一般来说这是不安全的。多字节变量的那些字节不是自己写入的。整个变量被读取、修改和写回。

所以线程 A 可以读取它,修改它,然后线程 B 读取它,线程 A 写入它,线程 B 修改并写入它。在这种情况下,来自线程 A 的更改将丢失。

您需要使用单独的变量或同步机制。

对于性能部分:您必须对其进行测试。不同的代码、硬件、数据大小等会给你关于什么是最优的不同答案。根据经验,先编写简单而正确的代码,然后在真正需要时进行优化。

【讨论】:

  • 你有任何来源/参考资料来支持这个吗?
【解决方案2】:

我认为这是安全的。如果我错了,请纠正我。但请记住 Mike Acton 在他的 article 中写的关于严格别名规则的内容:

总是假定char*可能引用任何对象的别名。因此,将任何类型的任何指针转换为 char* 类型可能有点不理想(对于具有广泛加载和存储的架构),但它是相当安全的。

我们可以做到以下几点:

    uint64_t shared_64 = 0x0102030405060708;
    char* thread_1_char = reinterpret_cast< char* >( &shared_64 );
    char* thread_2_char = reinterpret_cast< char* >( &shared_64 ) + 1;
    char* thread_3_char = reinterpret_cast< char* >( &shared_64 ) + 2;

    char& thread_1_ref = *thread_1_char;
    char& thread_2_ref = *thread_2_char;
    // and so on
    thread_1_ref = 1; // from one thread
    //...
    thread_2_ref = 2; // from another thread

现在每个thread_n_ref 变量都是一个不同的内存位置,请记住主题启动者所说的:

一个线程只能访问某个字节,所以不存在字节争用。

来自this

始终允许不同的执行线程同时访问(读取和修改)不同的内存位置,没有干扰也没有同步要求。

我得出结论,从不同线程访问 int64 的不同字节是安全的。

【讨论】:

    猜你喜欢
    • 2018-03-12
    • 2021-09-04
    • 1970-01-01
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    相关资源
    最近更新 更多