进程内多线程共享与独占资源
在操作系统中,进程是资源分配的基本单位,而线程是CPU调度的基本单位。一个进程可以包含多个线程,这些线程在执行时,会共享进程所拥有的资源,同时也会有一些资源是线程独占的。
一、共享资源
进程地址空间:
进程内的所有线程共享同一进程地址空间,这意味着它们可以访问进程中的全局变量、静态变量以及堆和栈区域(虽然每个线程有自己的栈,但栈区域是线程特有的部分,而堆区域是共享的)。
文件描述符表:
线程可以共享进程打开的文件描述符表,这使得多个线程可以同时读写同一个文件。
信号处理程序:
进程级的信号处理程序对于所有线程都是可见的,虽然每个线程可以设置自己的线程特定信号处理掩码。
进程控制信息:
线程共享进程的控制信息,如进程ID、父进程ID、进程组ID、会话ID等。
某些I/O缓存:
某些I/O操作(如标准输入输出)的缓存可能是由进程内所有线程共享的。
二、独占资源
线程栈:
每个线程都有自己独立的栈空间,用于存储局部变量、函数调用信息以及返回地址等。
线程控制块(TCB):
每个线程都有一个唯一的线程控制块,它包含了线程的调度信息、状态信息、优先级、上下文信息等。
寄存器:
虽然物理寄存器是共享的,但每个线程在执行时,都会有自己的逻辑寄存器状态,这是通过线程上下文切换来实现的。
错误码:
每个线程都有自己独立的错误码,用于记录线程执行过程中遇到的错误。
信号掩码:
每个线程可以设置自己的信号掩码,以控制哪些信号可以被该线程接收。
三、代码举例
以下是一个使用C语言和POSIX线程(pthread)库编写的简单示例,用于展示进程内多线程共享和独占资源的情况。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
// 共享的全局变量
int shared_global_var = 0;
// 线程函数
void* thread_func(void* arg) {
int thread_num = *(int*)arg;
// 访问共享的全局变量
printf("Thread %d: Before increment, shared_global_var = %d\n", thread_num, shared_global_var);
// 对共享的全局变量进行操作(模拟临界区)
pthread_mutex_t* mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutex, NULL);
pthread_mutex_lock(mutex);
shared_global_var++;
pthread_mutex_unlock(mutex);
free(mutex); // 注意:这里只是为了示例,实际使用中应该避免这样频繁地分配和释放互斥锁
printf("Thread %d: After increment, shared_global_var = %d\n", thread_num, shared_global_var);
// 每个线程有自己的线程号和栈空间(虽然栈空间在代码中不可见,但它是实际存在的)
printf("Thread %d: Unique thread ID = %lu\n", thread_num, pthread_self());
// 线程可以访问自己的局部变量(不共享)
int local_var = thread_num * 10;
printf("Thread %d: Local variable = %d\n", thread_num, local_var);
return NULL;
}
int main() {
pthread_t threads[2];
int thread_nums[2] = {1, 2};
// 创建两个线程
for (int i = 0; i < 2; i++) {
pthread_create(&threads[i], NULL, thread_func, &thread_nums[i]);
}
// 等待两个线程完成
for (int i = 0; i < 2; i++) {
pthread_join(threads[i], NULL);
}
printf("Main thread: Final value of shared_global_var = %d\n", shared_global_var);
return 0;
}
在这个示例中,我们创建了两个线程,它们共享一个全局变量shared_global_var
。每个线程都有自己的线程号和栈空间(虽然栈空间在代码中不可见,但它是实际存在的,并且由操作系统管理)。线程函数内,我们还展示了线程如何操作共享的全局变量,并如何访问自己的局部变量(这些局部变量是不共享的)。
需要注意的是,在实际的多线程编程中,对共享资源的访问需要进行同步控制,以避免竞态条件和数据不一致的问题。在上面的示例中,我们使用了互斥锁(pthread_mutex_t
)来对共享的全局变量进行保护,但示例中的互斥锁分配和释放方式仅用于教学目的,并不推荐在实际应用中使用。在实际应用中,应该使用线程池或全局的互斥锁对象来管理对共享资源的访问。