【C语言进程与线程】

文章目录


前言

在 C 语言开发中,并发编程是一个绕不开的重要话题,而"进程"和"线程"则是实现并发的两种核心方式。它们属于操作系统层面的概念,但在实际开发中,C 语言通常通过系统调用和线程库来对其进行操作。


一、进程基础概念

1. 什么是进程

进程(Process)是程序的一次执行过程,是操作系统进行资源分配的基本单位。

简单理解:

  • 程序 = 静态代码
  • 进程 = 运行中的程序

当你执行一个程序时,操作系统会为其分配内存、打开文件、建立运行环境,这个运行中的实例就是进程。


2. 进程的特点

  • 拥有独立的地址空间(堆、栈、全局变量)
  • 资源独立(文件描述符、内存等)
  • 进程之间默认相互隔离
  • 创建和切换开销较大
  • 安全性高

3. 获取进程ID

c 复制代码
#include <stdio.h>
#include <unistd.h>

int main() {
    printf("PID = %d\n", getpid());
    return 0;
}

二、线程基础概念

1. 什么是线程

线程(Thread)是进程中的一个执行单元,是 CPU 调度的基本单位。

一个进程可以包含多个线程,所有线程共享进程资源。


2. 线程的特点

  • 共享进程地址空间
  • 资源共享(堆、全局变量)
  • 创建和切换开销小
  • 通信方便
  • 容易产生数据竞争

3. 线程创建

c 复制代码
#include <stdio.h>
#include <pthread.h>

void* func(void* arg) {
    printf("Thread running\n");
    return NULL;
}

int main() {
    pthread_t tid;
    pthread_create(&tid, NULL, func, NULL);
    pthread_join(tid, NULL);
    return 0;
}

编译:

bash 复制代码
gcc test.c -o test -pthread

三、进程 vs 线程

对比项 进程 线程
资源分配 独立 共享
地址空间 独立 共享
创建开销
切换开销
通信方式 IPC 共享变量
安全性

四、C语言中创建进程(fork)

1. fork函数介绍

fork() 用于创建子进程,是 Linux/Unix 系统中最常用的进程创建方式。

返回值:

  • 子进程中返回 0
  • 父进程中返回 子进程PID
  • 出错返回 -1

2. 示例代码

c 复制代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
    pid_t pid = fork();

    if (pid == 0) {
        printf("Child: PID=%d\n", getpid());
    } else {
        printf("Parent: PID=%d, Child PID=%d\n", getpid(), pid);
    }

    return 0;
}

3. 执行特点

  • fork之后会执行两次(父子进程)
  • 执行顺序不确定(由操作系统调度)

五、进程地址空间验证

c 复制代码
#include <stdio.h>
#include <unistd.h>

int main() {
    int x = 10;
    pid_t pid = fork();

    if (pid == 0) {
        x = 20;
        printf("Child x=%d\n", x);
    } else {
        x = 30;
        printf("Parent x=%d\n", x);
    }
}

说明:

进程之间变量互不影响 → 地址空间独立


六、C语言中创建线程(pthread)

1. 常用函数

  • pthread_create:创建线程
  • pthread_join:等待线程结束
  • pthread_self:获取线程ID

2. 示例代码

c 复制代码
#include <stdio.h>
#include <pthread.h>

void* run(void* arg) {
    printf("Thread ID: %lu\n", pthread_self());
    return NULL;
}

int main() {
    pthread_t t1, t2;

    pthread_create(&t1, NULL, run, NULL);
    pthread_create(&t2, NULL, run, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    return 0;
}

七、线程共享数据问题

c 复制代码
#include <stdio.h>
#include <pthread.h>

int count = 0;

void* add(void* arg) {
    for (int i = 0; i < 100000; i++) {
        count++;
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;

    pthread_create(&t1, NULL, add, NULL);
    pthread_create(&t2, NULL, add, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    printf("count = %d\n", count);
}

问题:

结果不等于 200000 → 发生竞态条件


八、互斥锁解决线程安全

c 复制代码
#include <stdio.h>
#include <pthread.h>

int count = 0;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void* add(void* arg) {
    for (int i = 0; i < 100000; i++) {
        pthread_mutex_lock(&lock);
        count++;
        pthread_mutex_unlock(&lock);
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;

    pthread_create(&t1, NULL, add, NULL);
    pthread_create(&t2, NULL, add, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    printf("count = %d\n", count);
    return 0;
}

九、进程通信(IPC)简介

由于进程之间内存隔离,需要使用 IPC 进行通信。

常见方式:

  • 管道(pipe)
  • 命名管道(FIFO)
  • 共享内存
  • 消息队列
  • 信号
  • Socket

示例:管道通信

c 复制代码
#include <stdio.h>
#include <unistd.h>

int main() {
    int fd[2];
    pipe(fd);

    if (fork() == 0) {
        close(fd[0]);
        write(fd[1], "hello", 6);
    } else {
        char buf[20];
        close(fd[1]);
        read(fd[0], buf, sizeof(buf));
        printf("recv: %s\n", buf);
    }
}

总结

本文系统介绍了 C 语言中的进程和线程:

  • 进程:独立、隔离、安全,但开销大
  • 线程:轻量、高效,但需要同步控制
  • fork:创建进程核心函数
  • pthread:线程开发核心库
  • IPC:进程通信基础

在实际开发中:

  • 高隔离 → 多进程
  • 高并发 → 多线程
相关推荐
冷小鱼1 小时前
多线程编程深度解析:Java与Python框架实战指南
java·开发语言·python·多线程
fox_lht1 小时前
第十一章 错误处理
开发语言·后端·rust
叼烟扛炮1 小时前
C++ 知识点12 构造函数
开发语言·c++·算法·构造函数
Byte Wizard1 小时前
C语言指针深入浅出4
c语言·开发语言
asdfg12589631 小时前
Java 大型项目设计的“内功心法”---面向对象和接口编程
java·开发语言
叼烟扛炮1 小时前
C++第八讲:string 类
开发语言·c++·算法·string
ch.ju1 小时前
Java programming Chapter Three——Array
java·开发语言
灵哎惹,凌沃敏1 小时前
CM3/CM4内核总线知识总结
c语言·arm开发·单片机
努力努力再努力wz2 小时前
【Qt入门系列】第一个 Qt Widgets 程序:项目创建、UI 文件、Hello World、对象树与 qDebug 日志
java·c语言·开发语言·数据结构·c++·qt·ui