一个进程内的多个线程共享哪些资源,独占哪些资源?

科技   2024-11-29 13:20   上海  

进程内多线程共享与独占资源

在操作系统中,进程是资源分配的基本单位,而线程是CPU调度的基本单位。一个进程可以包含多个线程,这些线程在执行时,会共享进程所拥有的资源,同时也会有一些资源是线程独占的。

一、共享资源

  1. 进程地址空间

  • 进程内的所有线程共享同一进程地址空间,这意味着它们可以访问进程中的全局变量、静态变量以及堆和栈区域(虽然每个线程有自己的栈,但栈区域是线程特有的部分,而堆区域是共享的)。
  • 文件描述符表

    • 线程可以共享进程打开的文件描述符表,这使得多个线程可以同时读写同一个文件。
  • 信号处理程序

    • 进程级的信号处理程序对于所有线程都是可见的,虽然每个线程可以设置自己的线程特定信号处理掩码。
  • 进程控制信息

    • 线程共享进程的控制信息,如进程ID、父进程ID、进程组ID、会话ID等。
  • 某些I/O缓存

    • 某些I/O操作(如标准输入输出)的缓存可能是由进程内所有线程共享的。

    二、独占资源

    1. 线程栈

    • 每个线程都有自己独立的栈空间,用于存储局部变量、函数调用信息以及返回地址等。
  • 线程控制块(TCB)

    • 每个线程都有一个唯一的线程控制块,它包含了线程的调度信息、状态信息、优先级、上下文信息等。
  • 寄存器

    • 虽然物理寄存器是共享的,但每个线程在执行时,都会有自己的逻辑寄存器状态,这是通过线程上下文切换来实现的。
  • 错误码

    • 每个线程都有自己独立的错误码,用于记录线程执行过程中遇到的错误。
  • 信号掩码

    • 每个线程可以设置自己的信号掩码,以控制哪些信号可以被该线程接收。

    三、代码举例

    以下是一个使用C语言和POSIX线程(pthread)库编写的简单示例,用于展示进程内多线程共享和独占资源的情况。

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>

    // 共享的全局变量
    int shared_global_var = 0;

    // 线程函数
    voidthread_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] = {12};
        
        // 创建两个线程
        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)来对共享的全局变量进行保护,但示例中的互斥锁分配和释放方式仅用于教学目的,并不推荐在实际应用中使用。在实际应用中,应该使用线程池或全局的互斥锁对象来管理对共享资源的访问。


    Qt教程
    致力于Qt教程,Qt技术交流,研发
     最新文章