【问题标题】:C/Linux: Alternating between threadsC/Linux:在线程之间交替
【发布时间】:2020-04-17 11:20:43
【问题描述】:

所以我有这个代码:

#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;
}

我从命令行给出三个单词,例如“一二三”,每个线程打印一个单词,同步,这样顺序总是正确的。

我是线程和信号量的新手,我的大脑目前习惯于 sem_wait(sem) 和 sem_post(sem) 之后,其中 sem 是同一个信号量。我要问的是对这段代码为什么工作以及它是如何工作的完整解释。为什么用 0 权限初始化信号量?为什么会有 sem_post(first_semaphore)?我很困惑。

【问题讨论】:

    标签: c linux multithreading synchronization


    【解决方案1】:

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

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

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

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

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

    【讨论】:

      【解决方案2】:

      注意:这是一个较长的评论,而不是完整的答案。

      我喜欢将信号量视为无信息令牌的阻塞队列。信号量的 count 是队列中的令牌数。

      从这个角度来看,你程序中的主线程创建了一个单一的令牌(从无到有,因为令牌 什么都没有),并通过调用 sem_post(&amp;semaphores[0]); 将令牌交给第一个工作线程.

      第一个工作人员在从其输入队列中获取令牌后能够完成其工作(即,当sem_wait(&amp;semaphores[th_data-&gt;id]); 返回时。完成工作后,它将令牌交给下一个线程:sem_post(&amp;semaphores[th_data-&gt;id + 1]);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-24
        • 1970-01-01
        • 2010-12-21
        • 1970-01-01
        • 2018-06-04
        • 1970-01-01
        相关资源
        最近更新 更多