c - C/Linux:在线程之间交替
问题描述
所以我有这个代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <semaphore.h>
#define nr_threads 3
sem_t semaphores[nr_threads];
typedef struct {
int id;
char *word;
}th_struct;
void *thread_function(void *arg)
{
th_struct *th_data = (th_struct *) arg;
sem_wait(&semaphores[th_data->id]);
printf("[thread#%d] %s\n", th_data->id, th_data->word);
sem_post(&semaphores[th_data->id + 1]);
return NULL;
}
int main(int argc, char **argv)
{
pthread_t tid[nr_threads];
th_struct th_data[nr_threads];
for(int i = 0; i < nr_threads; i++){
if (sem_init(&semaphores[i], 0, 1) != 0){
perror("Could not init semaphore");
return -1;
}
}
sem_post(&semaphores[0]);
for(int i = 0; i < nr_threads; i++){
th_data[i].id = i;
th_data[i].word = argv[i + 1];
pthread_create(&tid[i], NULL, thread_function, &th_data[i]);
}
for(int i = 0; i < nr_threads; i++){
pthread_join(tid[i], NULL);
}
for(int i = 0; i < nr_threads; i++)
sem_destroy(&semaphores[i]);
return 0;
}
我从命令行给出 3 个单词,例如“一二三”,每个线程同步打印一个单词,以便顺序始终正确。
我是线程和信号量的新手,我的大脑目前习惯于 sem_wait(sem) 和 sem_post(sem) 之后,其中 sem 是相同的信号量。我要问的是对这段代码为什么工作以及它是如何工作的完整解释。为什么用 0 权限初始化信号量?为什么会有 sem_post(first_semaphore)?我很困惑。
解决方案
首先,该代码中有一个错误...
完成工作后,每个线程无条件地调用sem_post()
下一个线程的信号量。因此,第三个线程将尝试访问semaphores[3]
不存在的。
现在发生了什么(假设错误不存在)是这样的:
- 创建并初始化 3 个信号量,以便它们立即被锁定
- 创建了3个线程,每个调用
sem_wait()
和阻塞(因为信号量被初始化为0) - 一个线程完成它的工作后,它调用
sem_post()
下一个的信号量,然后从sem_wait()
这是基本思想,但要让它运行,需要有人调用sem_post()
第一个信号量。所以这就是sem_post(&semaphores[0])
main() 中有这个的原因。
推荐阅读
- rx-java - 用一个值初始化 RxJava 流
- java - UserRepository 在 @Autowired 中返回 null
- laravel - 自动备份 MySQL 数据库到谷歌驱动器
- azure - 在 Azure 自动化 Powershell 脚本中使用参数数组
- java - 如何在Android中保持从baseAdapter接收到的奇数个按钮为三角形?
- android - Android Studio 平台工具-无法下载 api 24/28
- node.js - 尝试使用 npm 命令安装任何软件包时出现错误
- vuejs2 - VeeValidate 不适用于内联编辑。我正在使用 v-for 和 v-if 进行内联编辑
- java - 模拟类在运行测试时从不总是给出空指针
- javascript - Javascript [Symbol.toPrimitive](hint) 转换函数