面试题答案
一键面试设计思路
- 线程组间同步:使用信号量来表示线程组A任务的完成情况。当线程组A完成任务后,释放一个信号量,线程组B在开始前等待这个信号量。
- 线程组内线程同步:在线程组B内,对于共享资源的访问,使用另一个信号量来控制按特定顺序访问。每个线程在访问共享资源前等待相应的信号量,访问完成后释放下一个线程需要的信号量。
关键代码片段
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
// 定义两个信号量,用于线程组间和线程组内同步
sem_t group_sync_sem;
sem_t inner_group_sem;
// 线程组A的任务函数
void* groupA_task(void* arg) {
// 模拟线程组A的任务
printf("Thread group A is working...\n");
// 任务完成后释放线程组间同步信号量
sem_post(&group_sync_sem);
return NULL;
}
// 线程组B的任务函数
void* groupB_task(void* arg) {
int thread_id = *((int*)arg);
// 等待线程组间同步信号量
sem_wait(&group_sync_sem);
// 等待线程组内同步信号量(根据特定顺序)
if (thread_id == 0) {
// 第一个线程不需要等待组内同步信号量
printf("Thread %d in group B starts first.\n", thread_id);
// 访问共享资源
// 访问完成后释放下一个线程需要的组内同步信号量
sem_post(&inner_group_sem);
} else {
sem_wait(&inner_group_sem);
printf("Thread %d in group B starts.\n", thread_id);
// 访问共享资源
// 访问完成后释放下一个线程需要的组内同步信号量(如果有)
if (thread_id < 2) {
sem_post(&inner_group_sem);
}
}
return NULL;
}
信号量操作详细解释
-
sem_t group_sync_sem;
:定义用于线程组间同步的信号量。- 初始化:在主线程中使用
sem_init(&group_sync_sem, 0, 0);
进行初始化,初始值为0,意味着线程组B开始时需要等待线程组A释放信号量。 sem_wait(&group_sync_sem);
:在线程组B的任务函数中,线程等待这个信号量。如果信号量值为0,线程将阻塞,直到线程组A调用sem_post(&group_sync_sem);
释放信号量。sem_post(&group_sync_sem);
:在线程组A的任务函数完成后,调用此函数释放信号量,通知线程组B可以开始。
- 初始化:在主线程中使用
-
sem_t inner_group_sem;
:定义用于线程组B内线程同步的信号量。- 初始化:在主线程中使用
sem_init(&inner_group_sem, 0, 0);
进行初始化,初始值为0,意味着除第一个线程外,其他线程需要等待前一个线程释放信号量。 sem_wait(&inner_group_sem);
:在线程组B内除第一个线程外的其他线程中,等待此信号量。当信号量值为0时,线程阻塞,直到前一个线程完成共享资源访问并调用sem_post(&inner_group_sem);
释放信号量。sem_post(&inner_group_sem);
:在线程组B内每个线程完成共享资源访问后,释放此信号量,允许下一个线程开始访问(如果有下一个线程)。
- 初始化:在主线程中使用
在主线程中,需要创建线程组A和线程组B的线程,并在程序结束时使用 sem_destroy(&group_sync_sem);
和 sem_destroy(&inner_group_sem);
销毁信号量。
int main() {
pthread_t groupA_thread;
pthread_t groupB_threads[3];
int thread_ids[3] = {0, 1, 2};
// 初始化信号量
sem_init(&group_sync_sem, 0, 0);
sem_init(&inner_group_sem, 0, 0);
// 创建线程组A的线程
pthread_create(&groupA_thread, NULL, groupA_task, NULL);
// 创建线程组B的线程
for (int i = 0; i < 3; i++) {
pthread_create(&groupB_threads[i], NULL, groupB_task, &thread_ids[i]);
}
// 等待线程组A和线程组B的线程完成
pthread_join(groupA_thread, NULL);
for (int i = 0; i < 3; i++) {
pthread_join(groupB_threads[i], NULL);
}
// 销毁信号量
sem_destroy(&group_sync_sem);
sem_destroy(&inner_group_sem);
return 0;
}