欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > C语言线程详解,及Linux中的一些相关命令

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

2024/10/31 8:58:13 来源:https://blog.csdn.net/weixin_65477256/article/details/142145440  浏览:    关键词:C语言线程详解,及Linux中的一些相关命令

文章目录

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

#include <pthread.h>
4.2 定义线程函数

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

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

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

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

示例代码:

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. 初始化互斥锁

    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, NULL);
    
  2. 加锁和解锁

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

    pthread_mutex_destroy(&mutex);
    

示例代码:

#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. 初始化条件变量

    pthread_cond_t cond;
    pthread_cond_init(&cond, NULL);
    
  2. 等待条件

    pthread_cond_wait(&cond, &mutex);
    
  3. 发送信号

    pthread_cond_signal(&cond);
    
  4. 销毁条件变量

    pthread_cond_destroy(&cond);
    

示例代码:

#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函数设置。优先级的管理依赖于操作系统的调度策略。以下是设置线程优先级的示例:

#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 线程退出
void* thread_function(void* arg) {// 执行一些操作pthread_exit(NULL); // 线程退出
}
7.2 取消线程
pthread_cancel(thread_id); // 请求取消线程

8. 示例代码

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

#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中提供了多种命令来管理和监控进程与线程,帮助开发者更好地进行系统调试和性能优化。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com