简体   繁体   English

您可以在 C 中的 pthread 之间使用通用结构共享互斥锁吗?

[英]Can you share mutexes using a common struct between pthreads in C?

I've been working on a multithreading exercise in C using POSIX threads that implements a thread pool design.我一直在使用实现线程池设计的 POSIX 线程在 C 中进行多线程练习。 My strategy was to embed the required and shared concurrency primitives in a struct instance then pass it to every pthread.我的策略是将所需和共享的并发原语嵌入到结构实例中,然后将其传递给每个 pthread。

I think my approach is flawed.我认为我的方法有缺陷。 It would appear do_work() is not dishing out jobs optimally and my book doesn't really explain a method for debugging these types of problems.看起来do_work()并没有以最佳方式分配工作,而且我的书并没有真正解释调试这些类型问题的方法。

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "list.h"
#include "cserver.h"

#define MAX_THREADS 5

struct thread_argvs {
    struct list *jobs_to_do;
    pthread_mutex_t job_lock;
    pthread_cond_t job_signal;
    int active;
}

struct job {
    int data; // arbitrary for example.
}

void * do_work(void *argv_values);

main(){
    
    // Stores jobs collected from client.
    struct job_list;
    list_init(&job_list);
    
    struct thread_argvs argvs;
    argvs.jobs_to_do = &job_list;
    argvs.job_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
    argvs.job_signal = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
    argvs.active = 1;
    
    pthread_t threads[MAX_THREADS];
    for (int i = 0; i < MAX_THREADS; i++){
         pthread_create(&thread_list[i], NULL, do_work, (void *) argvs);
    }
    
    /* connect to a client in-between here */
        
    for (;;){
        
        struct job *new_job = malloc(sizeof(struct job));
        new_job = get_job_from_client();  
        list_push(&job_list, &new_job);
        pthread_cond_signal(&argv.job_signal);
        
        if (new_job.data == -1){ // final job
            argv.active = 0;
            break;
        }
    }
    
    for (int i = 0; i < MAX_THREADS; i++) {
        pthread_cond_signal(&argv.job_signal);
    }

    for (int i = 0; i < MAX_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    return 0;
}

void * do_work(void *argv_values){

    struct thread_argvs *argvs = (struct thread_argvs *) argv_values;
    struct job *next_job;
    
    while(argvs.active == 1){
    
        next_job = NULL;
        
        pthread_mutex_lock(&(argvs->job_lock));
        pthread_cond_wait(&(argvs->job_signal), &(argvs->job_lock));
        
        if (list_size(argvs->jobs_to_do) > 0) {
            next_job = list_pop(&jobs_to_do);
        }
        
        pthread_mutex_unlock(&(argvs->job_lock));

        if (new_job != NULL) {
            do_something_with_job(next_job->data);
            free(next_job);
            next_job = NULL;
        }
    }
    
    pthread_exit(0);
}

You code can easily deadlock.你的代码很容易死锁。 All the calls to pthread_cond_signal can occur while no thread is blocked on the condition variable.当条件变量上没有线程被阻塞时,所有对pthread_cond_signal的调用都可能发生。 Then the first thread to call pthread_cond_wait can just block forever.然后第一个调用pthread_cond_wait的线程可以永远阻塞。

You must never call pthread_cond_wait without first confirming (while holding the mutex!) that the thing you are going to wait for hasn't already happened.在没有首先确认(同时持有互斥锁!)您要等待的事情尚未发生之前,您绝不能调用pthread_cond_wait

From the top:从一开始:

    while(argvs.active == 1){

Every bit of storage that is shared between threads must have a synchronization guarantee.线程之间共享的每一位存储都必须有同步保证。 Where is the guarnatee for the line quoted above?上面引用的行的保证在哪里? Next up;接下来; Condition variables have no memory.条件变量没有记忆。 There is no doubt, if somebody sees something like:毫无疑问,如果有人看到类似的东西:

        pthread_mutex_lock(&(argvs->job_lock));
        pthread_cond_wait(&(argvs->job_signal), &(argvs->job_lock));

That they missed the message about how condition variables work.他们错过了关于条件变量如何工作的信息。 It is in the name condition variables , which means the before waiting upon them, there is some condition that you must check upon, and failing that condition being true, choose to wait upon it.它的名称为condition variables ,这意味着在等待它们之前,有一些condition必须检查,如果条件不成立,请选择wait它。

Next: a supplicant of the last - when you awake on a condition variable, you need to check that the condition is satisfied before continuing.下一步:最后一个请求者 - 当您在条件变量上awake时,您需要在继续之前检查条件是否满足。 An example follows:一个例子如下:

    Lock(&VeryImportantThing);
    while (SomethingVeryImportant is not Set) {
        CondWait(&VeryImportantCond, &VeryImportantLock);
    }
    SomethingVeryImportant = Vanilla;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM