进程通信与线程通信:全面总结 + 使用场景 + 优缺点 + 使用方法

文章目录

  • 进程与线程的通信方式全面总结
  • [第一部分:线程通信(Thread Communication)](#第一部分:线程通信(Thread Communication))
    • [1. 全局变量共享(最简单方式)](#1. 全局变量共享(最简单方式))
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
      • [✔ 使用方法](#✔ 使用方法)
    • [2. 互斥锁(Mutex):解决互斥问题](#2. 互斥锁(Mutex):解决互斥问题)
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
      • [✔ 使用方法](#✔ 使用方法)
    • [3. 信号量(Semaphore):互斥 + 同步二合一](#3. 信号量(Semaphore):互斥 + 同步二合一)
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
      • [✔ 使用方法](#✔ 使用方法)
    • [4. 条件变量(Condition Variable)](#4. 条件变量(Condition Variable))
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
      • [✔ 使用方法](#✔ 使用方法)
    • [5. 读写锁(RWLock)](#5. 读写锁(RWLock))
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
      • [✔ 使用方法](#✔ 使用方法)
    • [6. 屏障(Barrier)](#6. 屏障(Barrier))
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
      • [✔ 使用方法](#✔ 使用方法)
  • 第二部分:进程通信(IPC)
    • [1. 匿名管道(pipe)](#1. 匿名管道(pipe))
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
      • [✔ 使用方法](#✔ 使用方法)
    • [2. 命名管道(FIFO)](#2. 命名管道(FIFO))
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
      • [✔ 使用方法](#✔ 使用方法)
    • [3. 消息队列(Message Queue)](#3. 消息队列(Message Queue))
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
    • [4. 共享内存(Shared Memory):最快 IPC](#4. 共享内存(Shared Memory):最快 IPC)
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
      • [✔ 使用方法](#✔ 使用方法)
    • [5. 信号量(semget / semop)](#5. 信号量(semget / semop))
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
    • [6. 信号(signal)](#6. 信号(signal))
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
    • [7. 套接字(socket)](#7. 套接字(socket))
      • [① UNIX 域套接字 ------ 本地进程通信最快方式](#① UNIX 域套接字 —— 本地进程通信最快方式)
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 使用方法](#✔ 使用方法)
      • [② TCP/IP 套接字 ------ 支持跨机器通信](#② TCP/IP 套接字 —— 支持跨机器通信)
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
    • [8. mmap 文件映射](#8. mmap 文件映射)
      • [✔ 使用场景](#✔ 使用场景)
      • [✔ 优点](#✔ 优点)
      • [✔ 缺点](#✔ 缺点)
  • 第三部分:两者对比总结(非常重要)
  • 最终总结(选择建议)
    • [✔ 如果是线程之间通信:](#✔ 如果是线程之间通信:)
    • [✔ 如果是进程之间通信:](#✔ 如果是进程之间通信:)

进程与线程的通信方式全面总结

(使用场景 + 优缺点 + 使用方式)

在 Linux 系统中,程序的并发执行通常依赖 进程(Process)线程(Thread)

它们在运行时需要共享数据、协作执行,这就产生了:

  • 进程间通信(IPC)
  • 线程间通信(同步与共享数据)

本篇文章通过系统化的方式,为你总结所有通信方式、各自适用的场景、优缺点,并给出示例代码,帮助你快速掌握 Linux 下的并发编程。


第一部分:线程通信(Thread Communication)

线程共享同一进程空间,它们本身没有"通信",而是共享变量 + 使用同步原语控制访问顺序。

线程通信的核心是:

✔ 共享内存

✔ 同步机制保证线程安全

常用方式如下:


1. 全局变量共享(最简单方式)

✔ 使用场景

  • 多个线程共享某个变量(计数器、状态标志等)

✔ 优点

  • 简单、自然、不需要系统调用
  • 速度最快(线程共享内存)

✔ 缺点

  • 必须使用锁保护
  • 容易产生数据竞争(race condition)

✔ 使用方法

c 复制代码
int shared_value = 0;

void* worker(void* arg) {
    shared_value++;
    return NULL;
}

2. 互斥锁(Mutex):解决互斥问题

✔ 使用场景

  • 多线程访问共享资源时要保护临界区
  • 解决:同时只有一个线程能执行关键代码

✔ 优点

  • 机制简单
  • 用途广泛、稳定可靠

✔ 缺点

  • 使用不当容易造成死锁
  • 不能解决同步(等待条件)问题

✔ 使用方法

c 复制代码
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_lock(&lock);
// 临界区
pthread_mutex_unlock(&lock);

3. 信号量(Semaphore):互斥 + 同步二合一

✔ 使用场景

  • 线程同步(例如生产者-消费者)
  • 控制可同时访问资源的线程数量(计数信号量)

✔ 优点

  • 能实现互斥,也能实现同步
  • 支持计数,比 mutex 更灵活

✔ 缺点

  • 比 mutex 更难理解
  • 使用不当可能导致死锁

✔ 使用方法

c 复制代码
sem_t sem;
sem_init(&sem, 0, 1);

sem_wait(&sem);   // P 操作
// 临界区
sem_post(&sem);   // V 操作

4. 条件变量(Condition Variable)

✔ 使用场景

  • 一个线程等待某个条件成立(如 shared_data > 0)
  • 广泛用于生产者-消费者模型

✔ 优点

  • 比忙等(while循环)高效
  • 能使线程睡眠直到被唤醒

✔ 缺点

  • 必须配合互斥锁使用
  • 逻辑比 mutex 略复杂

✔ 使用方法

c 复制代码
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_lock(&mutex);
while (shared_data == 0)
    pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);

5. 读写锁(RWLock)

✔ 使用场景

  • 多个线程需要同时读取共享数据(读多写少)

✔ 优点

  • 允许多个线程读,提高并发度
  • 写操作仍然保证互斥

✔ 缺点

  • 写锁容易饥饿
  • 使用复杂度比 mutex 高

✔ 使用方法

c 复制代码
pthread_rwlock_t rwlock;

pthread_rwlock_rdlock(&rwlock);
// 读操作
pthread_rwlock_unlock(&rwlock);

6. 屏障(Barrier)

✔ 使用场景

  • 一组线程需要在某个同步点汇合,然后一起继续执行

✔ 优点

  • 解决"一次性全体同步"问题
  • 在多阶段算法中常用(并行计算)

✔ 缺点

  • 不常用于业务逻辑
  • 使用起来稍复杂

✔ 使用方法

c 复制代码
pthread_barrier_t barrier;
pthread_barrier_init(&barrier, NULL, thread_num);

pthread_barrier_wait(&barrier);

第二部分:进程通信(IPC)

进程完全隔离,不共享内存,因此需要借助内核的 IPC 机制交换数据。

按难度从简单到复杂排列:


1. 匿名管道(pipe)

✔ 使用场景

  • 父子进程通信
  • shell 的 ls | grep 就是管道

✔ 优点

  • 简单易用
  • 单向数据流很适合流水线处理

✔ 缺点

  • 只能用于父子进程
  • 单向流动、不能同时双向发

✔ 使用方法

c 复制代码
int fd[2];
pipe(fd);
write(fd[1], "hello", 5);
read(fd[0], buf, 5);

2. 命名管道(FIFO)

✔ 使用场景

  • 任意两个进程通信
  • 简单客户端-服务端模型

✔ 优点

  • 支持无关进程通信
  • API 简单

✔ 缺点

  • 同样是单向
  • 不适合彩信大量数据

✔ 使用方法

c 复制代码
mkfifo("myfifo", 0666);
int fd = open("myfifo", O_WRONLY);
write(fd, "hi", 2);

3. 消息队列(Message Queue)

✔ 使用场景

  • 多个进程之间发送消息
  • 适合小型命令通信(非大量数据)

✔ 优点

  • 有消息边界,不会出现黏包问题
  • 内核管理消息队列,稳定可靠

✔ 缺点

  • 队列大小有限制
  • 不适合大量数据传输

4. 共享内存(Shared Memory):最快 IPC

✔ 使用场景

  • 大量数据交换(视频、音频、图片等)
  • 性能要求极高的应用

✔ 优点

  • 最快的 IPC(几乎零开销)
  • 数据直接在同一块内存中共享

✔ 缺点

  • 必须使用同步机制(如信号量)
  • 编程复杂度略高

✔ 使用方法

c 复制代码
int shmid = shmget(1234, 1024, 0666|IPC_CREAT);
char* mem = shmat(shmid, NULL, 0);
// 读写 mem 即可

5. 信号量(semget / semop)

✔ 使用场景

  • 进程间同步(配合共享内存)
  • 避免多个进程同时访问共享资源

✔ 优点

  • 操作非常高效
  • 跨进程同步能力强

✔ 缺点

  • 只能做同步,不传数据
  • 使用略复杂

6. 信号(signal)

✔ 使用场景

  • 进程间发送异步事件(比如 kill 通知)

✔ 优点

  • 实现简单
  • 适合发送控制指令(终止进程)

✔ 缺点

  • 只能传递简单事件
  • 不适合传输数据

7. 套接字(socket)

分两种:

① UNIX 域套接字 ------ 本地进程通信最快方式

✔ 使用场景

  • 本地客户端-服务端
  • Nginx、Docker、MySQL 常用

✔ 优点

  • 和 TCP 几乎一样,但更快
  • 使用文件路径作为地址

✔ 使用方法

c 复制代码
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
bind(sock, ... "/tmp/test.sock");

② TCP/IP 套接字 ------ 支持跨机器通信

✔ 使用场景

  • 网络程序必须用它(Web 服务器、聊天程序)

✔ 优点

  • 可跨主机通信
  • API 通用、功能强大

✔ 缺点

  • 效率比 UDS 和共享内存低
  • 涉及网络协议栈处理

8. mmap 文件映射

✔ 使用场景

  • 文件共享数据
  • 多进程共享内存但使用文件作为底层媒介

✔ 优点

  • 实现共享内存的另一种方式
  • 适合大量数据

✔ 缺点

  • 需要文件系统支持
  • 不适合频繁的同步操作

第三部分:两者对比总结(非常重要)

通信类型 适用对象 速度 是否共享内存 工程常用性
线程通信 同一进程内线程 🚀 非常快 ✔ 是 极常用
进程通信 完全独立的进程 ⚡ 中等 ❌ 否 常用

最终总结(选择建议)

✔ 如果是线程之间通信:

优先选择:

复制代码
共享变量 → mutex → cond → sem → rwlock

✔ 如果是进程之间通信:

顺序建议如下:

复制代码
大量数据 → 共享内存(最快)
本地通信 → UNIX 域套接字
跨主机 → TCP/IP socket
简单消息 → 队列
通知事件 → signal
父子进程 → pipe
相关推荐
fish_xk42 分钟前
用c++写控制台贪吃蛇
开发语言·c++
r***013844 分钟前
linux上redis升级
linux·运维·redis
好奇的菜鸟1 小时前
如何在 Ubuntu 系统上完全移除 Docker 及其所有数据
linux·ubuntu·docker
mit6.8241 小时前
海外服务器clone gitee慢怎么办
运维·服务器·gitee
Unlyrical1 小时前
线程池详解(c++手撕线程池)
c++·线程·线程池·c++11
BD_Marathon1 小时前
【Zookeeper】客户端命令行——节点类型
linux·服务器·zookeeper
myw0712052 小时前
湘大头歌程-Ride to Office练习笔记
c语言·数据结构·笔记·算法
H_BB2 小时前
算法详解:滑动窗口机制
数据结构·c++·算法·滑动窗口