多线程环境中初始化的内存语义(C++)

     2023-02-22     166

关键词:

【中文标题】多线程环境中初始化的内存语义(C++)【英文标题】:Memory semantics of initialization in multithread environment (C++) 【发布时间】:2017-07-20 02:09:16 【问题描述】:

我不确定 C++ 初始化过程的内存语义。 假设我们有以下程序。

#include <iostream>
#include <thread>

using namespace std;

void func(int* arr, int s)

    for (int i = 0; i < s; ++i)
    
        cout << arr[i] << endl;
    


int main(int argc, char *argv[])

    int *a = new int[10];
    for (int i = 0; i < 10; ++i)
    
        a[i] = i;
    

    // Do I need some sort of memory barrier here?
    std::thread t(func, a, 10);
    t.join();
    return 0;

新线程会看到正确初始化的数组吗?或者我是否需要在两者之间插入某种内存屏障。 C++语言如何定义初始化的内存语义?

我担心的是所有对数组 a[10] 的写入都可能位于一个 cpu 的写入缓冲区中,并且我们在不同的 cpu 上启动了一个新线程,它可能不会观察到初始化写入。

我们是否需要用于初始化的内存栅栏,以便稍后在不同 cpu 上运行的线程能够观察到?

【问题讨论】:

【参考方案1】:

在执行线程构造函数之前父进程中的操作与子进程中运行的线程过程之间存在“先发生”关系。特别是标准说(f 是线程过程):

同步:构造函数调用的完成与f副本的调用开始同步。

这可以在[thread.thread.constr]部分找到

【讨论】:

感谢您的引用。我很难阅读标准。我找到了你的报价。通过“同步”,我想这意味着编译器可能会在调用 f 的副本之前插入栅栏,以确保观察到调用 f 之前的所有存储? @OliverYoung:该标准没有提及内存栅栏,因为并非所有 CPU 架构都需要它们。该标准说明了编译器需要确保副作用可见的位置,以及操作重叠(创建竞争条件)的位置,并且编译器负责使用任何 CPU 功能提供指定的行为。 我明白了。需要非常清楚的是,初始化部分同步/“之前发生”的 f 副本的调用。这意味着没有竞争条件,也不需要同步操作,对吧? @OliverYoung:正确。虽然说“不需要额外的同步操作”会更正确,因为启动线程已经是一个同步操作,正如这个标准引用所记录的那样。

多线程环境中静态变量的C++初始化

】多线程环境中静态变量的C++初始化【英文标题】:C++Initializationofstaticvariableinmultithreadedenvironment【发布时间】:2017-05-2914:03:17【问题描述】:我正在努力寻找一种在C++中初始化类的静态成员的正确方法。上下文是随机数生成。... 查看详情

juc多线程:jmm内存模型与volatile内存语义(代码片段)

...:        Java内存模型是Java虚拟机定义的一种多线程访问Java内存各个变量的访问规范,主要围绕如何解决并发过程中的原子性、可见性、有序性这三个问题来解决线程的安全问题。        Java内存模型将内存分... 查看详情

双检查锁失效

...检查锁定(以下称为DCL)已被广泛当做多线程环境下延迟初始化的一种高效手段。遗憾的是,在Java中,如果没有额外的同步,它并不可靠。在其它语言中,如c++,实现DCL,需要依赖于处理器的内存模型、编译器实行的重排序以... 查看详情

关于 c++ 初始化程序的内存一致性

】关于c++初始化程序的内存一致性【英文标题】:Memorycoherencewithrespecttoc++initializers【发布时间】:2015-09-1813:23:00【问题描述】:如果我在一个线程中设置变量的值并在另一个线程中读取它,我会用锁保护它以确保第二个线程读... 查看详情

在多线程环境中使用 PyCurl 时程序消耗的内存不断增长

】在多线程环境中使用PyCurl时程序消耗的内存不断增长【英文标题】:ProgramconsumedmemorykeepsgrowingwhileusingPyCurlinmultithreadedenvironment【发布时间】:2022-01-1501:36:20【问题描述】:当PyCurl在多线程环境中用于并发HTTPAPI调用时,Python程... 查看详情

并发编程-内存模型

在C++1x标准中,一个重大的更新就是引入了C++多线程内存模型。本文的主要目的在于介绍C++多线程内存模型涉及到的一些原理和概念,以帮助大家理解C++多线程内存模型的作用和意义。 1.顺序一致性模型(SequentialConsistency)在介... 查看详情

单例模式双重检查(dcl)引发的多线程问题

...内存过程2.  调用DoubleCheckedLock的构造函数给instance初始化过程3.  将incetance指向分配的内存空间在这三个过程之间,由于JVM的“优化”机制,如果出现多线程并发访问的情况,就会出现A线程在执行过程2的时候,已... 查看详情

volatile内存语义

读内存语义:当读一个volatile变量时,JMM将该线程对应的本地内存置为无效,从主内存中读取共享变量。写内存语义:当写一个volatile变量时,JMM将该线程对应的本地内存中的共享变量值刷新到主内存。读写内存语义加起来,就... 查看详情

使用 std::thread (C++ 11) 多线程无法正常工作

...d::thread的多线程是如何工作的。这是我的程序执行步骤:初始化5x5整数矩阵,包含在“Toto”类中的唯一值“42”(在main中初始化 查看详情

在 MFC C++ 中使用多线程

...】:我对在CPU、MFCC++上使用多线程感到陌生。我正在尝试初始化两个CWinThreads并将它们作为工作线程同时运行,它在我的头文件中CWinThread*m_thread;CWinThread*m_thread1;在我的cpp文件中,我试图这样称呼它们CdecoderD3D9App* 查看详情

volatile写读的内存语义

1,当写一个volatile变量时,JMM(java内存模型)会把该线程本地内存中的所有共享变量刷新到主内存中去2,当读取一个volatile变量时,该线程会将本地内存置为无效,线程将从主内存中读取共享变量。总结,volatile变量可以实现线程... 查看详情

多线程下的volatile关键字使用详解及java先行发生原则(代码片段)

...,以至于许多程序员都习惯不去使用它,遇到需要处理多线程数据竞争问题的时候一律使用synchronized来进行同步。了解volatile变量的语义对了解多线程操作的其他特性很有意义,在本文中我们将介绍volatile的语义到底是什么。由... 查看详情

在多线程环境中使用 .Net UdpClient

...个实例只通过UdpClient类发送UDP数据包。它在其构造函数中初始化UdpClient,仅用于发送数据包。它看起来像:publicclassAprivateUdpClient 查看详情

多线程编程之windows环境下创建新线程

在Win32API中,创建线程的基本函数是CreateThread,而_beginthread(ex)是C++运行库的函数。为什么要有两个呢?因为C++运行库里面有一些函数使用了全局量,如果使用CreateThread的情况下使用这些C++运行库的函数,就会出现不安全的问题。... 查看详情

volatile语义

volatile在Java内存模型(JMM)中,保证共享变量对所有线程可见,但不保证原子性。volatile语义是同步,通过共享变量的方式,完成线程间的通信。为什么需要volatileJava内存模型中抽象、简化了计算机物理设备,分成工作内存和主... 查看详情

使用三个线程在一个字符后面顺序添加字符(代码片段)

一、先来了解一下多线程中fina域l的内存语义,大家都知道多线程并行执行时,就会出现编译器执行时并不是顺序执行代码的,因此我们必须加入一些关键字来使得我们的程序能够顺序执行,就是所谓的内存可见性,下面先来了... 查看详情

多线程设计,保护C++中的全局成员

...具有只读访问权限的全局对象。在打开线程之前,我必须初始化全局对象并用数据填充它们。如何保护我的全局对象的集合函数,但仍可以从主函数访问?现在的示例代码:myCla 查看详情

多线程程序的 C++ 定时器中断

】多线程程序的C++定时器中断【英文标题】:C++timerinterruptformultithreadedprogram【发布时间】:2017-12-1300:44:43【问题描述】:我正在Linux环境中进行开发。假设我有3个线程,t1、t2和t3在我的软件中运行(使用pthread实现)。线程t1和t2... 查看详情