C语言线程详解,及Linux中的一些相关命令
文章目录
以下是关于C语言中线程的详细讲解,包含线程的创建、管理、同步、终止等方面的内容,并增加了对线程和进程的区别与联系的讲解,以及相关知识的扩展。同时,添加了Linux中对线程和进程相关操作的命令。
1. 线程的基本概念
- 线程:线程是进程中的一个执行流,多个线程共享同一进程的资源(如内存、文件描述符等),可以并发执行。
- 进程:进程是操作系统分配资源的基本单位,每个进程都有自己的地址空间。线程是轻量级的进程。
2. 线程与进程的区别与联系
2.1 区别
-
资源分配:
- 进程:每个进程都有独立的地址空间和资源,进程之间的通信需要通过IPC(进程间通信)机制,如管道、消息队列、共享内存等。
- 线程:线程共享同一进程的地址空间和资源,线程之间的通信相对简单,可以直接访问共享数据。
-
创建和销毁:
- 进程:创建和销毁进程的开销较大,因为需要分配和管理独立的资源。
- 线程:创建和销毁线程的开销较小,因为线程共享进程的资源。
-
调度:
- 进程:操作系统对进程的调度相对复杂,涉及到进程的状态管理和上下文切换。
- 线程:线程的调度相对简单,线程的上下文切换速度更快。
-
稳定性:
- 进程:一个进程的崩溃不会影响其他进程的运行。
- 线程:一个线程的崩溃可能导致整个进程的崩溃,因为所有线程共享同一进程的资源。
2.2 联系
- 共享资源:线程是进程的一部分,多个线程可以共享同一进程的资源,如内存和文件描述符。
- 并发执行:线程和进程都可以实现并发执行,提升程序的性能和响应能力。
- 调度机制:操作系统对线程和进程的调度机制有相似之处,都是通过调度算法来管理执行。
3. 线程的底层实现
线程的底层实现依赖于操作系统的调度和管理机制。不同的操作系统可能会有不同的线程实现方式,但通常包括以下几个方面:
3.1 线程调度
操作系统使用调度算法来管理线程的执行。常见的调度算法包括:
- 先来先服务(FCFS):按照线程到达的顺序进行调度。
- 时间片轮转(Round Robin):为每个线程分配一个时间片,时间片用完后切换到下一个线程。
- 优先级调度:根据线程的优先级进行调度,高优先级线程优先执行。
3.2 线程上下文切换
当操作系统需要切换执行的线程时,会进行上下文切换。上下文切换的过程包括:
- 保存当前线程的上下文(寄存器、程序计数器等)。
- 加载下一个线程的上下文。
- 更新调度信息。
上下文切换是一个相对昂贵的操作,频繁的上下文切换会影响程序的性能。
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)
互斥锁用于保护共享资源,确保同一时间只有一个线程可以访问该资源。使用互斥锁的步骤如下:
-
初始化互斥锁:
pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL);
-
加锁和解锁:
pthread_mutex_lock(&mutex); // 访问共享资源 pthread_mutex_unlock(&mutex);
-
销毁互斥锁:
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)
条件变量用于线程之间的信号传递,允许一个线程等待某个条件的发生。使用条件变量的步骤如下:
-
初始化条件变量:
pthread_cond_t cond; pthread_cond_init(&cond, NULL);
-
等待条件:
pthread_cond_wait(&cond, &mutex);
-
发送信号:
pthread_cond_signal(&cond);
-
销毁条件变量:
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, ¶m);
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中提供了多种命令来管理和监控进程与线程,帮助开发者更好地进行系统调试和性能优化。
原文地址:https://blog.csdn.net/weixin_65477256/article/details/142145440
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!