C++ 什么时候我们应该选择其他IPC而不是直接内存访问来进行线程间通信

C++ 什么时候我们应该选择其他IPC而不是直接内存访问来进行线程间通信,c++,linux,multithreading,networking,ipc,C++,Linux,Multithreading,Networking,Ipc,由于同一进程中的线程共享相同的地址空间,我们可以通过直接内存访问和互斥在这些线程之间传输数据,因此在本文中,我有以下问题: 全局变量和互斥量对于线程间通信来说都足够了吗 如果问题1为假,在什么情况下我们应该选择其他IPC而不是直接内存访问?或者说,在什么情况下,其他IPC手段比使用全局变量和互斥体更合适 谢谢 更新 感谢@ssyam指出关于“全局变量”的错误陈述。 我选择添加一节,而不是更正原始段落,因为 对这一段有很多评论。这里有一个想法: 即使两个线程正在访问相同的内存,也不一定意味着它们看

由于同一进程中的线程共享相同的地址空间,我们可以通过直接内存访问和互斥在这些线程之间传输数据,因此在本文中,我有以下问题:

  • 全局变量和互斥量对于线程间通信来说都足够了吗
  • 如果问题1为假,在什么情况下我们应该选择其他IPC而不是直接内存访问?或者说,在什么情况下,其他IPC手段比使用全局变量和互斥体更合适
  • 谢谢

    更新
    感谢@ssyam指出关于“全局变量”的错误陈述。
    我选择添加一节,而不是更正原始段落,因为 对这一段有很多评论。

    这里有一个想法:

    即使两个线程正在访问相同的内存,也不一定意味着它们看到相同的值。如果一个线程正在更新该值,那么另一个线程可以看到过时的值—更新之前从处理器本地缓存获取的值。为了防止这种情况发生,您需要使用互斥锁或其他一些技术来同步线程

    不管采用哪种技术,本地缓存都必须使用所谓的“内存屏障”进行刷新,这是一项非常昂贵的操作,因为这将要求所有处理器停止正在执行的操作,并等待操作完成


    另一方面,IPC调用不一定需要这样做

    好吧,全局变量在单线程代码中很糟糕,而在多线程代码中,它们通常成为一个主要问题。即使使用互斥锁正确地完成同步,它们也会成为瓶颈。另外,互斥锁通常不足以进行线程间通信。您通常至少还需要条件变量


    也就是说,在多线程应用程序中,在内存中的线程之间传输数据是合理的。但是,一般来说,我发现处理显式锁定是不可行的。当传输类似于消息传递系统的数据时,即使消息是内存中的数据结构,代码也往往不那么复杂,效率更高。从这个意义上讲,消息在任何时候都只由一个线程使用,并且唯一发生的锁定是消息传递设施中隐含的。

    不需要全局变量。请记住,线程例程可以接受参数,因此它可以是任何类型的变量,包括动态分配的变量

    通常,您会希望在类中“包装”线程,大致如下:

    struct Thread
    {
        Thread() : m_thread(&Thread::run, this) {}
        void run()
        {
            // access the current object's member variables, eg:
            do_something_with(m_myvar);
        }
    
        Object m_myvar;
        std::thread m_thread;
    };
    
    但如果我们撇开全局变量的这个小细节不谈,你的#1是对的。。。通过受互斥锁保护的变量(无论是消息队列、布尔值等)和可选的
    条件_变量
    (用作唤醒触发器)进行通信几乎总是可行的方法

    例如,我几乎总是使用线程安全的消息队列(即队列+互斥体+条件变量)在线程之间进行通信(生产者/消费者模式),这是一种非常有效的方法来隔离线程并允许它们进行通信


    事实上,在很少的情况下,在单个进程中,除了直接内存访问之外,其他的东西是有意义的

    我现在能想到的就是,如果您已经有了一些进程间代码(例如套接字或共享内存),那么您可以重用这些代码,以便实现统一的接口,无论是进程内通信还是进程间通信。但不要自欺欺人,它的效率不如直接内存访问。然而,统一界面的好处可以很容易地克服效率的损失。我认为你真的需要逐案处理这类事情。

    关于(1)我同意迪特玛·库尔的观点,条件变量是最小集合的一部分


    关于(2)我倾向于选择IPC,只要我能负担得起少量的开销(主要是一个系统调用和一些数据复制),因为IPC带来的方便性和灵活性。管道、消息队列、域套接字等都具有内置的原子性和同步性,它们根据情况需要提供阻塞、非阻塞或定时读/写。您可以将它们填充到
    select
    语句中,而无需执行任何特殊操作。它耗电巨大,成本很低,而且不需要重新设计轮子。

    作为旁注(这里只是吹毛求疵…)IPC的意思是“进程间通信”,因此它不适用于线程(进程内通信)。但无论如何,我们都明白你的意思@我对你的唠叨感到厌烦。进程间通信这个术语出现在线程之前,但我从未听说过有人在应用于进程内通信时对这个术语犹豫不决。至少在linux中,进程和线程之间并没有太大区别。@Duck实际上你是对的。查看Wikipedia(我知道…)的定义,术语“IPC”似乎也用于线程间通信(即使它扩展为“进程间…”)。我猜我的强迫症又发作了,我的错。我对此困惑了很长时间。我们有一个多线程应用程序,其中大约有100个线程,所有线程都使用直接共享内存访问,而不是消息传递(这里的消息传递是指进程间通信的方式)。我发现代码变得很难看,到处都是互斥体。问题是确定何时使用带有互斥体和条件变量的直接memroy访问以及何时使用消息传递方式的边界在哪里。除了简单和传统的直接内存访问,我什么时候应该选择消息传递?@StevePeng消息传递只是直接内存访问的另一种形式。它通常涉及存储消息的队列,以及