首页 > 解决方案 > 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)?我很困惑。

标签: clinuxmultithreadingsynchronization

解决方案


首先,该代码中有一个错误...

完成工作后,每个线程无条件地调用sem_post()下一个线程的信号量。因此,第三个线程将尝试访问semaphores[3]不存在的。

现在发生了什么(假设错误不存在)是这样的:

  • 创建并初始化 3 个信号量,以便它们立即被锁定
  • 创建了3个线程,每个调用sem_wait()和阻塞(因为信号量被初始化为0)
  • 一个线程完成它的工作后,它调用sem_post()下一个的信号量,然后从sem_wait()

这是基本思想,但要让它运行,需要有人调用sem_post()第一个信号量。所以这就是sem_post(&semaphores[0])main() 中有这个的原因。


推荐阅读