c - 使用 pthreads 管理链表

标签 c multithreading linked-list pthreads simulation

我正在尝试模拟一家银行,其中有一排客户由一个链表表示,其中一个线程计算客户每单位时间走进来的概率(以预设概率)并将客户添加到最后线,而几个出纳员线程从线的开头删除了一个客户,并且在每次模拟期间,我总是在看似不可预测的点出现段错误。下面是我用于添加和从列表中删除的代码。该错误似乎是因为客户线程正在尝试添加,而出纳员正在删除。

void addToQ(int x, void *arg){
    printf("ADD ATTEMPT\n");
    struct shiftInfo *info = (struct shiftInfo *) arg;
    if (head -> ID == -1){ //No clients in line
        head -> ID = x;
        head -> next = dummy;
        tail = head;
    }

    else{ //clients already in line
        tail -> next = (NODE *)malloc(sizeof(NODE));
        tail = tail -> next;
        tail -> ID = x;
        tail -> next = dummy;
        info -> inQ++;
    }
    printf("ADD SUCCESS\n");
}
//Removes node closest to root
//Assumes: root != end
void removeFromQ(void *arg){
    printf("REMOVE ATTEMPT\n");
    struct shiftInfo *info = (struct shiftInfo *) arg;
    if (head -> next == dummy){ //only one element
        printf("SCENARIO 1\n");
        head -> ID = -1;
    }
    else{
        printf("SCENARIO 2\n");
        curr = head -> next;
        head = curr -> next;
        printf("Halfway\n");
        if ((head -> next == NULL) || (head -> next == dummy))
            tail = head;
    }
    info -> inQ--;
    printf("REMOVE SUCCESS\n");
}

线程函数如下:

void *customerT(void *arg){
    int custID = 100;
    float newCust = 0;
    struct shiftInfo *info = (struct shiftInfo *) arg;
    float aRate = info -> arrivalRate;
    pthread_mutex_lock (&start); //Ensures Customers don't start before Tellers get to work
    pthread_mutex_unlock (&start);
    while(0<info -> simTime){
        newCust = (double)rand() / (double)RAND_MAX;
        if (newCust <= aRate){
            pthread_mutex_lock (&start);
            addToQ(custID,(void *)info);
            pthread_mutex_unlock (&start);
            custID++;
            }
        sleep(1/60);
    }
    pthread_exit(NULL);
 }


void *teller(void *arg){
    struct shiftInfo *info = (struct shiftInfo *) arg;
    int clientID;
    int clients = info -> inQ;
    pthread_mutex_lock (&start); //Ensures tellers dont start before customers arrive
    pthread_mutex_unlock (&start);
    while(0<info -> simTime){
        pthread_mutex_lock (&accessQ);
        clients = info -> inQ;
        if(head -> ID > 0){
            pthread_mutex_lock (&start);
            removeFromQ((void *)info);
            pthread_mutex_unlock (&start);
            printf("CLIENT OBTAINED\n");
        }
        printf("In Q %d\n", clients);
        pthread_mutex_unlock (&accessQ);
        sleep((info -> serviceTime)/60);
        }
    pthread_exit(NULL);
}

如果相关,这里是管理器线程函数:

//Creates Customer thread, Teller threads, and timer thread
void *mainThread(void *info){
    head = (NODE *)malloc(sizeof(NODE));
    head -> ID = -1;
    head -> next = dummy;
    tail = head;
    int status;
    struct shiftInfo *I = info; 
    pthread_mutex_init(&start, NULL);
    pthread_mutex_init(&removeID, NULL);
    pthread_mutex_init(&accessQ, NULL);
    pthread_mutex_lock (&start);

    printf("Scheduling Tellers\n");
    pthread_t threads[(I -> tellers)];
    for (int i = 0; i < (I -> tellers); i++){
        I -> threadID = i;
        status = pthread_create(&threads[i], NULL, teller, (void *)info);
        if (status){
            printf("ERROR CODE: %d\n", status);
            exit(-1);
        }
    }

    printf("Preparing Customers\n");
    pthread_t customer;
    status = pthread_create(&customer, NULL, customerT, (void *)info);
        if (status){
            printf("ERROR CODE: %d\n", status);
            exit(-1);
        }

    printf("Making Timer\n");
    pthread_t time;
        status = pthread_create(&time, NULL, timer, (void *)info);
        if (status){
            printf("ERROR CODE: %d\n", status);
            exit(-1);
        }

    pthread_mutex_unlock (&start);
}

最佳答案

这里的代码看起来是错误的:

curr = head -> next;
head = curr -> next;

考虑您的列表如下所示的情况:head -> node -> dummy。运行上述代码后,head 将指向 dummy,这是您肯定不希望看到的。尝试将代码更改为:

curr = head;
head = curr -> next;

编辑:您获得负面客户的原因是,在 addToQ 中,当列表开始为空时(您的上半部分),您不会增加 info->inQ if 语句)。您始终需要 info->inQ++,就像您始终在 removeFromQueue 中拥有 info->inQ-- 一样。

关于c - 使用 pthreads 管理链表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27210568/

相关文章:

c - C中的线程本地数据

java - java中的多个并行线程不会终止

当我将数据推送到初始化堆栈时,C 链表不会改变

python : how to know max size of a queue

c++ - pthreads:在主线程上执行功能

c++ - 瓶颈 C++ 排序函数 Wi-Fi 信号

c - 在单个遍历链表中交换从开始到结束的第 k 个位置

c - 当操作系统取消固定远程内存缓冲区时,RDMA WRITE/READ 的行为如何?

c - 尝试理解 C 程序

C - 动态内存分配