MST

星途 面试题库

面试题:C语言中POSIX线程创建及简单同步

请用C语言结合POSIX线程库创建两个线程,一个线程负责计算1到100的累加和,另一个线程负责打印从A到Z的字母。并且使用互斥锁保证在累加和计算完成后再开始打印字母。请写出完整代码,并解释互斥锁的作用原理。
33.9万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

// 定义互斥锁
pthread_mutex_t mutex;
// 定义条件变量
pthread_cond_t cond;
// 用于存储累加和
int sum = 0;

// 计算1到100的累加和的线程函数
void* sum_thread(void* arg) {
    for (int i = 1; i <= 100; i++) {
        sum += i;
    }
    // 锁住互斥锁
    pthread_mutex_lock(&mutex);
    // 发送条件变量信号
    pthread_cond_signal(&cond);
    // 解锁互斥锁
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}

// 打印从A到Z字母的线程函数
void* print_thread(void* arg) {
    // 锁住互斥锁
    pthread_mutex_lock(&mutex);
    // 等待条件变量信号,等待时会解锁互斥锁,被唤醒后重新加锁
    pthread_cond_wait(&cond, &mutex);
    for (char ch = 'A'; ch <= 'Z'; ch++) {
        printf("%c ", ch);
    }
    printf("\n");
    // 解锁互斥锁
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}

int main() {
    pthread_t tid1, tid2;

    // 初始化互斥锁
    pthread_mutex_init(&mutex, NULL);
    // 初始化条件变量
    pthread_cond_init(&cond, NULL);

    // 创建计算累加和的线程
    if (pthread_create(&tid1, NULL, sum_thread, NULL) != 0) {
        perror("pthread_create");
        return 1;
    }
    // 创建打印字母的线程
    if (pthread_create(&tid2, NULL, print_thread, NULL) != 0) {
        perror("pthread_create");
        return 1;
    }

    // 等待两个线程结束
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    // 销毁互斥锁
    pthread_mutex_destroy(&mutex);
    // 销毁条件变量
    pthread_cond_destroy(&cond);

    printf("1到100的累加和为: %d\n", sum);

    return 0;
}

互斥锁的作用原理

  1. 基本概念:互斥锁(Mutex,即Mutual Exclusion的缩写)是一种特殊的二元信号量,它的值只能是0或1。其主要作用是保证在同一时刻只有一个线程能够访问共享资源,防止多个线程同时访问共享资源而导致数据竞争和不一致的问题。
  2. 工作流程
    • 加锁:当一个线程调用pthread_mutex_lock函数尝试获取互斥锁时,如果互斥锁当前的值为1(表示未被锁定),则该函数会将互斥锁的值设为0(表示已被锁定),然后线程可以继续执行临界区(共享资源访问代码)的代码。如果互斥锁当前的值为0(已被其他线程锁定),则调用pthread_mutex_lock的线程会被阻塞,直到互斥锁被解锁。
    • 解锁:当线程完成对共享资源的访问后,调用pthread_mutex_unlock函数将互斥锁的值设为1(解锁),此时如果有其他线程正在等待获取该互斥锁,则系统会唤醒其中一个等待线程,让其获取互斥锁并进入临界区。在本代码中,通过互斥锁和条件变量结合使用,保证了打印字母的线程在累加和计算完成后才开始执行。计算累加和的线程在完成计算后,通过互斥锁保护条件变量的发送操作,打印线程在等待条件变量时,先获取互斥锁,等待过程中会释放互斥锁,被唤醒后重新获取互斥锁,从而确保线程同步。