簡體   English   中英

您可以在 C 中的 pthread 之間使用通用結構共享互斥鎖嗎?

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

我一直在使用實現線程池設計的 POSIX 線程在 C 中進行多線程練習。 我的策略是將所需和共享的並發原語嵌入到結構實例中,然后將其傳遞給每個 pthread。

我認為我的方法有缺陷。 看起來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);
}

你的代碼很容易死鎖。 當條件變量上沒有線程被阻塞時,所有對pthread_cond_signal的調用都可能發生。 然后第一個調用pthread_cond_wait的線程可以永遠阻塞。

在沒有首先確認(同時持有互斥鎖!)您要等待的事情尚未發生之前,您絕不能調用pthread_cond_wait

從一開始:

    while(argvs.active == 1){

線程之間共享的每一位存儲都必須有同步保證。 上面引用的行的保證在哪里? 接下來; 條件變量沒有記憶。 毫無疑問,如果有人看到類似的東西:

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

他們錯過了關於條件變量如何工作的信息。 它的名稱為condition variables ,這意味着在等待它們之前,有一些condition必須檢查,如果條件不成立,請選擇wait它。

下一步:最后一個請求者 - 當您在條件變量上awake時,您需要在繼續之前檢查條件是否滿足。 一個例子如下:

    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