当前位置:首页>Linux>Linux笔试题:多线程交替打印数字——互斥锁与条件变量的同步实战

Linux笔试题:多线程交替打印数字——互斥锁与条件变量的同步实战

  • 2026-09-02 20:16:17
Linux笔试题:多线程交替打印数字——互斥锁与条件变量的同步实战
-begin-

大家好,我是一个爱分享的牛马程序员,工作中碰到,加上自己理解,很高兴给大家分享。

题目:在Linux系统中,编写一个多线程程序,实现两个线程交替打印数字:线程A打印1、3、5…(奇数),线程B打印2、4、6…(偶数),要求输出顺序为1、2、3、4…依次递增,且最终打印到20结束。

详细分析过程:

1.线程同步需求:两个线程需严格交替执行,即线程A打印后必须等待线程B打印,反之亦然。这种“顺序依赖”需通过同步机制实现,常用的有互斥锁(mutex)+条件变量(condition variable)组合。
2.核心思路:
◦用一个全局变量(如count)记录当前需打印的数字,初始值为1。
◦线程A负责打印奇数:当count为奇数时打印,然后count自增,通知线程B;若count为偶数则等待。
◦线程B负责打印偶数:当count为偶数时打印,然后count自增,通知线程A;若count为奇数则等待。
◦用互斥锁保护count的读写,避免竞争条件;用条件变量实现线程间的等待与唤醒。
3.退出条件:当count超过20时,两个线程退出循环,程序结束。

关键代码:

#include <stdio.h>

#include <pthread.h>

#include <stdlib.h>

#define MAX_NUM 20

int count = 1; // 全局计数,从1开始

pthread_mutex_t mutex; // 互斥锁

pthread_cond_t cond;   // 条件变量

// 线程A:打印奇数

void *thread_a(void *arg) {

   while (1) {

       pthread_mutex_lock(&mutex); // 加锁

       // 若当前是偶数,等待线程B打印后唤醒

       while (count % 2 == 0) {

           pthread_cond_wait(&cond, &mutex);

       }

       // 检查是否超过最大值,退出

       if (count > MAX_NUM) {

           pthread_mutex_unlock(&mutex);

           break;

       }

       // 打印奇数

       printf("线程A: %d\n", count);

       count++; // 计数自增

       pthread_cond_signal(&cond); // 唤醒线程B

       pthread_mutex_unlock(&mutex); // 解锁

   }

   return NULL;

}

// 线程B:打印偶数

void *thread_b(void *arg) {

   while (1) {

       pthread_mutex_lock(&mutex); // 加锁

       // 若当前是奇数,等待线程A打印后唤醒

       while (count % 2 != 0) {

           pthread_cond_wait(&cond, &mutex);

       }

       // 检查是否超过最大值,退出

       if (count > MAX_NUM) {

           pthread_mutex_unlock(&mutex);

           break;

       }

       // 打印偶数

       printf("线程B: %d\n", count);

       count++; // 计数自增

       pthread_cond_signal(&cond); // 唤醒线程A

       pthread_mutex_unlock(&mutex); // 解锁

   }

   return NULL;

}

int main() {

   pthread_t tid_a, tid_b;

   // 初始化互斥锁和条件变量

   if (pthread_mutex_init(&mutex, NULL) != 0) {

       perror("mutex init failed");

       exit(EXIT_FAILURE);

   }

   if (pthread_cond_init(&cond, NULL) != 0) {

       perror("cond init failed");

       pthread_mutex_destroy(&mutex);

       exit(EXIT_FAILURE);

   }

   // 创建线程

   if (pthread_create(&tid_a, NULL, thread_a, NULL) != 0) {

       perror("create thread a failed");

       goto cleanup;

   }

   if (pthread_create(&tid_b, NULL, thread_b, NULL) != 0) {

       perror("create thread b failed");

       pthread_cancel(tid_a);

       goto cleanup;

   }

   // 等待线程结束

   pthread_join(tid_a, NULL);

   pthread_join(tid_b, NULL);

cleanup:

   // 销毁互斥锁和条件变量

   pthread_mutex_destroy(&mutex);

   pthread_cond_destroy(&cond);

   return 0;

}

代码说明:

•互斥锁(mutex):确保count的读写操作是原子的,避免两个线程同时修改或读取导致的数据不一致。
•条件变量(cond):实现线程间的等待与唤醒。pthread_cond_wait(&cond, &mutex)会释放已持有的mutex,并阻塞等待,直到被pthread_cond_signal唤醒后重新获取mutex。
•循环检查条件:while (count % 2 == 0)而非if,因为线程可能被虚假唤醒(即使没有收到信号也可能唤醒),循环检查可确保只有条件满足时才继续执行。
•退出逻辑:当count超过20时,线程退出循环,主线程通过pthread_join等待线程结束后,销毁锁和条件变量,释放资源。

运行结果示例:

线程A: 1

线程B: 2

线程A: 3

线程B: 4

...

线程A: 19

线程B: 20

常见考点:

•互斥锁与条件变量的配合使用(条件变量必须在持有锁的情况下使用);
•pthread_cond_wait的作用(释放锁+阻塞等待,唤醒后重新获取锁);
•虚假唤醒的处理(用while循环而非if检查条件);
•线程创建与销毁的资源释放(必须销毁初始化的锁和条件变量)。
-end-



如果文章对你有提升,帮忙点赞,分享,关注。非常感谢

最新文章

随机文章