当前位置:首页>Linux>华为笔试高频题:嵌入式Linux下的线程同步机制,从互斥锁到条件变量的实战解析

华为笔试高频题:嵌入式Linux下的线程同步机制,从互斥锁到条件变量的实战解析

  • 2026-09-10 05:17:31
华为笔试高频题:嵌入式Linux下的线程同步机制,从互斥锁到条件变量的实战解析

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

-begin-

题目:在嵌入式Linux系统中,编写一个多线程程序,实现以下功能:

1.创建两个线程:线程A负责生成随机数(1-100),每1秒生成一个,存入全局数组(容量10);
2.线程B负责读取全局数组中的数据,当数组中有数据时,取出并打印,每读取一个数据后休眠500ms;
3.使用同步机制确保数组操作的线程安全,且线程B不会在数组为空时阻塞等待。

详细分析过程:

一、核心考点拆解

本题聚焦多线程同步,是华为嵌入式岗位笔试的高频题,主要考察:

•线程创建与销毁(pthread_create、pthread_join);
•互斥锁(pthread_mutex_t)解决临界资源(全局数组)的并发访问问题;
•条件变量(pthread_cond_t)实现线程间的通信:当数组为空时,线程B阻塞等待;当数组有数据时,线程A唤醒线程B。

二、关键设计思路

4.全局数据结构:
◦定义数组buf[10]存储随机数;
◦用in_idx(写入索引)和out_idx(读取索引)记录数组使用状态,count记录当前数据个数(count = (in_idx - out_idx + 10) % 10)。
5.同步机制:
◦互斥锁mutex:保护buf、in_idx、out_idx、count的操作,确保每次只有一个线程修改或访问;
◦条件变量cond:线程B在count == 0时调用pthread_cond_wait阻塞,释放锁并等待;线程A写入数据后调用pthread_cond_signal唤醒线程B。
6.线程逻辑:
◦线程A:循环生成随机数,加锁后判断数组是否已满(count == 10),若满则跳过(或阻塞,本题简化为跳过),否则写入数据并更新in_idx和count,解锁后唤醒线程B,休眠1秒。
◦线程B:循环加锁,若count == 0则等待条件变量(自动释放锁,被唤醒时重新获取锁);否则取出数据,更新out_idx和count,解锁后打印数据,休眠500ms。

三、代码实现

#include <stdio.h>

#include <pthread.h>

#include <stdlib.h>

#include <unistd.h>

#include <time.h>

#define BUF_SIZE 10

int buf[BUF_SIZE];

int in_idx = 0;   // 写入索引

int out_idx = 0;  // 读取索引

int count = 0;    // 当前数据个数

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // 互斥锁

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;     // 条件变量

// 线程A:生成随机数

void *thread_a(void *arg) {

   srand(time(NULL));  // 初始化随机数种子

   while (1) {

       pthread_mutex_lock(&mutex);

       if (count < BUF_SIZE) {  // 数组未满

           int num = rand() % 100 + 1;  // 生成1-100的随机数

           buf[in_idx] = num;

           in_idx = (in_idx + 1) % BUF_SIZE;

           count++;

           printf("线程A写入:%d,当前计数:%d\n", num, count);

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

       } else {

           printf("线程A:缓冲区满,跳过写入\n");

       }

       pthread_mutex_unlock(&mutex);

       sleep(1);  // 每1秒生成一个

   }

   return NULL;

}

// 线程B:读取并打印

void *thread_b(void *arg) {

   while (1) {

       pthread_mutex_lock(&mutex);

       // 若缓冲区为空,等待条件变量(自动释放锁,被唤醒时重新加锁)

       while (count == 0) {

           printf("线程B:缓冲区空,等待数据...\n");

           pthread_cond_wait(&cond, &mutex);

       }

       // 读取数据

       int data = buf[out_idx];

       out_idx = (out_idx + 1) % BUF_SIZE;

       count--;

       printf("线程B读取:%d,剩余计数:%d\n", data, count);

       pthread_mutex_unlock(&mutex);

       usleep(500000);  // 休眠500ms

   }

   return NULL;

}

int main() {

   pthread_t tid_a, tid_b;

   // 创建线程

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

       perror("pthread_create thread_a failed");

       return -1;

   }

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

       perror("pthread_create thread_b failed");

       return -1;

   }

   // 等待线程(实际中可加信号处理退出,此处简化为无限循环)

   pthread_join(tid_a, NULL);

   pthread_join(tid_b, NULL);

   // 清理资源(实际中需在退出时调用)

   pthread_mutex_destroy(&mutex);

   pthread_cond_destroy(&cond);

   return 0;

}

四、代码解析与考点总结

7.线程安全:互斥锁确保buf、in_idx、out_idx、count的操作原子性,避免多线程同时读写导致的数据混乱(如数组越界、计数错误)。
8.条件变量作用:解决“线程B忙等”问题——若不使用条件变量,线程B需频繁加锁检查count,浪费CPU资源;使用pthread_cond_wait后,线程B在无数据时进入阻塞态,被唤醒时才继续执行,降低系统开销。
9.易错点:
◦pthread_cond_wait必须放在while循环中检查条件(而非if),因为线程可能被虚假唤醒(如系统信号中断),需重新判断条件;
◦加锁和解锁的范围需精确:仅保护临界资源操作,避免将休眠等耗时操作包含在锁内,否则会导致线程A阻塞无法写入数据。
10.华为考点延伸:实际面试中可能会追问“若要实现生产者消费者模型的阻塞队列(缓冲区满时生产者阻塞,空时消费者阻塞),如何修改代码?”——只需在线程A中添加while (count == BUF_SIZE) pthread_cond_wait(&full_cond, &mutex);,并新增一个条件变量full_cond即可。

通过本题可掌握多线程同步的核心机制,这也是华为等大厂嵌入式岗位考察的重点——不仅要会用API,更要理解其底层逻辑与设计思想。

-end-

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

最新文章

随机文章