C语言线程详解,及Linux中的一些相关命令

文章目录

      • [1. 线程的基本概念](#1. 线程的基本概念)
      • [2. 线程与进程的区别与联系](#2. 线程与进程的区别与联系)
        • [2.1 区别](#2.1 区别)
        • [2.2 联系](#2.2 联系)
      • [3. 线程的底层实现](#3. 线程的底层实现)
        • [3.1 线程调度](#3.1 线程调度)
        • [3.2 线程上下文切换](#3.2 线程上下文切换)
        • [3.3 线程栈](#3.3 线程栈)
      • [4. 线程的创建](#4. 线程的创建)
        • [4.1 包含头文件](#4.1 包含头文件)
        • [4.2 定义线程函数](#4.2 定义线程函数)
        • [4.3 创建线程](#4.3 创建线程)
      • [5. 线程的同步](#5. 线程的同步)
        • [5.1 互斥锁(Mutex)](#5.1 互斥锁(Mutex))
        • [5.2 条件变量(Condition Variables)](#5.2 条件变量(Condition Variables))
      • [6. 线程的优先级](#6. 线程的优先级)
      • [7. 线程的终止](#7. 线程的终止)
        • [7.1 线程退出](#7.1 线程退出)
        • [7.2 取消线程](#7.2 取消线程)
      • [8. 示例代码](#8. 示例代码)
      • [9. Linux中对线程和进程相关操作的命令](#9. Linux中对线程和进程相关操作的命令)
        • [9.1 查看进程](#9.1 查看进程)
        • [9.2 查看线程](#9.2 查看线程)
        • [9.3 杀死进程](#9.3 杀死进程)
        • [9.4 杀死线程](#9.4 杀死线程)
        • [9.5 创建进程](#9.5 创建进程)
        • [9.6 创建线程](#9.6 创建线程)
      • [10. 总结](#10. 总结)

以下是关于C语言中线程的详细讲解,包含线程的创建、管理、同步、终止等方面的内容,并增加了对线程和进程的区别与联系的讲解,以及相关知识的扩展。同时,添加了Linux中对线程和进程相关操作的命令。

1. 线程的基本概念

  • 线程:线程是进程中的一个执行流,多个线程共享同一进程的资源(如内存、文件描述符等),可以并发执行。
  • 进程:进程是操作系统分配资源的基本单位,每个进程都有自己的地址空间。线程是轻量级的进程。

2. 线程与进程的区别与联系

2.1 区别
  1. 资源分配

    • 进程:每个进程都有独立的地址空间和资源,进程之间的通信需要通过IPC(进程间通信)机制,如管道、消息队列、共享内存等。
    • 线程:线程共享同一进程的地址空间和资源,线程之间的通信相对简单,可以直接访问共享数据。
  2. 创建和销毁

    • 进程:创建和销毁进程的开销较大,因为需要分配和管理独立的资源。
    • 线程:创建和销毁线程的开销较小,因为线程共享进程的资源。
  3. 调度

    • 进程:操作系统对进程的调度相对复杂,涉及到进程的状态管理和上下文切换。
    • 线程:线程的调度相对简单,线程的上下文切换速度更快。
  4. 稳定性

    • 进程:一个进程的崩溃不会影响其他进程的运行。
    • 线程:一个线程的崩溃可能导致整个进程的崩溃,因为所有线程共享同一进程的资源。
2.2 联系
  • 共享资源:线程是进程的一部分,多个线程可以共享同一进程的资源,如内存和文件描述符。
  • 并发执行:线程和进程都可以实现并发执行,提升程序的性能和响应能力。
  • 调度机制:操作系统对线程和进程的调度机制有相似之处,都是通过调度算法来管理执行。

3. 线程的底层实现

线程的底层实现依赖于操作系统的调度和管理机制。不同的操作系统可能会有不同的线程实现方式,但通常包括以下几个方面:

3.1 线程调度

操作系统使用调度算法来管理线程的执行。常见的调度算法包括:

  • 先来先服务(FCFS):按照线程到达的顺序进行调度。
  • 时间片轮转(Round Robin):为每个线程分配一个时间片,时间片用完后切换到下一个线程。
  • 优先级调度:根据线程的优先级进行调度,高优先级线程优先执行。
3.2 线程上下文切换

当操作系统需要切换执行的线程时,会进行上下文切换。上下文切换的过程包括:

  1. 保存当前线程的上下文(寄存器、程序计数器等)。
  2. 加载下一个线程的上下文。
  3. 更新调度信息。

上下文切换是一个相对昂贵的操作,频繁的上下文切换会影响程序的性能。

3.3 线程栈

每个线程都有自己的栈空间,用于存储局部变量、函数参数和返回地址。线程栈的大小可以在创建线程时指定,通常默认大小为1MB。

4. 线程的创建

在C语言中,线程通常通过POSIX线程(pthread)库来创建和管理。以下是创建线程的基本步骤:

4.1 包含头文件

在使用pthread库之前,需要包含相应的头文件:

c 复制代码
#include <pthread.h>
4.2 定义线程函数

线程函数必须返回void*类型,并接受一个void*类型的参数。这个参数可以用来传递数据给线程。

c 复制代码
void* thread_function(void* arg) {
    int* num = (int*)arg; // 将参数转换为整数指针
    printf("Thread number: %d\n", *num);
    return NULL;
}
4.3 创建线程

使用pthread_create函数创建线程。该函数的原型如下:

c 复制代码
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);
  • thread:指向线程标识符的指针。
  • attr:线程属性,通常为NULL
  • start_routine:线程执行的函数。
  • arg:传递给线程函数的参数。

示例代码:

c 复制代码
int main() {
    pthread_t thread_id;
    int thread_num = 1; // 线程参数
    pthread_create(&thread_id, NULL, thread_function, &thread_num);
    pthread_join(thread_id, NULL); // 等待线程结束
    return 0;
}

5. 线程的同步

由于多个线程可能会同时访问共享资源,因此需要同步机制来避免数据竞争。常用的同步机制包括:

5.1 互斥锁(Mutex)

互斥锁用于保护共享资源,确保同一时间只有一个线程可以访问该资源。使用互斥锁的步骤如下:

  1. 初始化互斥锁

    c 复制代码
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, NULL);
  2. 加锁和解锁

    c 复制代码
    pthread_mutex_lock(&mutex);
    // 访问共享资源
    pthread_mutex_unlock(&mutex);
  3. 销毁互斥锁

    c 复制代码
    pthread_mutex_destroy(&mutex);

示例代码:

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

pthread_mutex_t mutex;

void* thread_function(void* arg) {
    pthread_mutex_lock(&mutex);
    printf("Thread is accessing shared resource.\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t thread_id[5];
    pthread_mutex_init(&mutex, NULL);
    
    for (int i = 0; i < 5; i++) {
        pthread_create(&thread_id[i], NULL, thread_function, NULL);
    }
    
    for (int i = 0; i < 5; i++) {
        pthread_join(thread_id[i], NULL);
    }
    
    pthread_mutex_destroy(&mutex);
    return 0;
}
5.2 条件变量(Condition Variables)

条件变量用于线程之间的信号传递,允许一个线程等待某个条件的发生。使用条件变量的步骤如下:

  1. 初始化条件变量

    c 复制代码
    pthread_cond_t cond;
    pthread_cond_init(&cond, NULL);
  2. 等待条件

    c 复制代码
    pthread_cond_wait(&cond, &mutex);
  3. 发送信号

    c 复制代码
    pthread_cond_signal(&cond);
  4. 销毁条件变量

    c 复制代码
    pthread_cond_destroy(&cond);

示例代码:

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

pthread_mutex_t mutex;
pthread_cond_t cond;
int ready = 0;

void* thread_function(void* arg) {
    pthread_mutex_lock(&mutex);
    while (!ready) {
        pthread_cond_wait(&cond, &mutex);
    }
    printf("Thread is running after condition is met.\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t thread_id;
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
    
    pthread_create(&thread_id, NULL, thread_function, NULL);
    
    // 模拟一些工作
    sleep(1);
    
    pthread_mutex_lock(&mutex);
    ready = 1; // 设置条件
    pthread_cond_signal(&cond); // 发送信号
    pthread_mutex_unlock(&mutex);
    
    pthread_join(thread_id, NULL);
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

6. 线程的优先级

在C语言中,线程的优先级可以通过pthread_setschedparam函数设置。优先级的管理依赖于操作系统的调度策略。以下是设置线程优先级的示例:

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

void* thread_function(void* arg) {
    // 线程执行的代码
    return NULL;
}

int main() {
    pthread_t thread_id;
    pthread_create(&thread_id, NULL, thread_function, NULL);
    
    struct sched_param param;
    param.sched_priority = 10; // 设置优先级
    pthread_setschedparam(thread_id, SCHED_FIFO, &param);
    
    pthread_join(thread_id, NULL);
    return 0;
}

7. 线程的终止

线程可以通过返回线程函数或调用pthread_exit函数来终止。使用pthread_cancel可以请求取消线程,但需要注意线程的状态。

7.1 线程退出
c 复制代码
void* thread_function(void* arg) {
    // 执行一些操作
    pthread_exit(NULL); // 线程退出
}
7.2 取消线程
c 复制代码
pthread_cancel(thread_id); // 请求取消线程

8. 示例代码

以下是一个完整的示例,展示了如何创建和使用线程,包括互斥锁和条件变量的使用:

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

pthread_mutex_t mutex;
pthread_cond_t cond;
int ready = 0;

void* thread_function(void* arg) {
    pthread_mutex_lock(&mutex);
    while (!ready) {
        pthread_cond_wait(&cond, &mutex);
    }
    printf("Thread is running after condition is met.\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t thread_id;
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);
    
    pthread_create(&thread_id, NULL, thread_function, NULL);
    
    // 模拟一些工作
    sleep(1);
    
    pthread_mutex_lock(&mutex);
    ready = 1; // 设置条件
    pthread_cond_signal(&cond); // 发送信号
    pthread_mutex_unlock(&mutex);
    
    pthread_join(thread_id, NULL);
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

9. Linux中对线程和进程相关操作的命令

9.1 查看进程
  • ps aux:查看当前系统中所有进程的信息。
  • top:实时查看系统中进程的资源使用情况。
9.2 查看线程
  • ps -eLf:查看系统中所有线程的信息。
  • top -H:在top命令中显示线程信息。
9.3 杀死进程
  • kill <pid>:发送信号终止指定进程。
  • kill -9 <pid>:强制终止指定进程。
9.4 杀死线程
  • 线程通常通过终止其所属的进程来结束,使用kill命令时指定进程ID(PID)即可。
9.5 创建进程
  • fork():在C语言中使用fork()系统调用创建新进程。
9.6 创建线程
  • pthread_create():在C语言中使用pthread_create()函数创建新线程。

10. 总结

C语言中的线程提供了并发执行的能力,通过使用pthread库,可以创建、管理和同步线程。理解线程的基本概念和操作是编写高效多线程程序的关键。线程与进程的区别在于资源分配、创建和销毁的开销、调度复杂性等方面,而它们之间的联系则体现在共享资源和并发执行的能力上。线程的底层实现涉及调度、上下文切换和线程栈等方面,掌握这些知识有助于更深入地理解多线程编程的性能和行为。线程的同步机制(如互斥锁和条件变量)是确保数据一致性和避免竞争条件的重要工具。Linux中提供了多种命令来管理和监控进程与线程,帮助开发者更好地进行系统调试和性能优化。

相关推荐
禁默8 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood14 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Code哈哈笑17 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
gb421528720 分钟前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端
程序猿进阶20 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
Youkiup22 分钟前
【linux 常用命令】
linux·运维·服务器
qq_4336184423 分钟前
shell 编程(二)
开发语言·bash·shell
qq_2975046126 分钟前
【解决】Linux更新系统内核后Nvidia-smi has failed...
linux·运维·服务器
zfoo-framework28 分钟前
【jenkins插件】
java