一些提示,以避免在这个pthreaded C程序中出现死锁

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些提示,以避免在这个pthreaded C程序中出现死锁相关的知识,希望对你有一定的参考价值。

我有一个任务器,它像一个生产者和3个CPU,像消费者和共享资源。 Tasker读取文件并放入共享资源,CPU执行并删除它。我使用了一个用于FIFO的环队列。我发现问题是由于条件变量,我的任务器完成后CPU线程没有终止,即他们仍在等待Tasker添加一些东西供他们删除。我希望在我杀死CPU线程之前清空共享资源,但它们会陷入死锁。对不起,由于我的调试,代码有点乱并且改变了。如果你们中的任何一个人能给我一些关于如何重新做的建议,我将不胜感激。谢谢。

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h> //used for exit
#include <string.h>
#include <unistd.h> // sleep function
#include <string.h>
#include <stdbool.h>

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t not_full = PTHREAD_COND_INITIALIZER;  //check till not full
pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER; //till not empty

void *task(void *n); //function of pthread
void *cpu(void *n);  //function of pthread

typedef struct
{
    int *buffer; //;//dynamic buffer
    int head;
    int tail;
    int buffsize;
    int state;
} queue;

//globals
pthread_t tid, cid1, cid2, cid3; //id
//queue *ptr;               //our object
FILE *fwptr; //log file
int tasker;

int main()
{
    queue pt; //initialize first
    queue *ptr = &pt;
    ptr->head = 0;
    ptr->tail = 0;
    ptr->buffer = (int *)malloc(sizeof(int) * 5);
    ptr->buffsize = 5;

    fwptr = fopen("fnew.txt", "w+"); //log

    pthread_create(&tid, NULL, &task, ptr);
    sleep(1);
    pthread_create(&cid1, NULL, &cpu, ptr);
    //pthread_create(&cid1, NULL, &cpu, ptr);
    pthread_create(&cid2, NULL, &cpu, ptr);
    pthread_create(&cid3, NULL, &cpu, ptr);
    pthread_join(tid, NULL);
    //pthread_mutex_lock(&lock);
    tasker = 1; //tasker finished so now close when empty, noneed ot mutex bc 1 writer
    //pthread_mutex_unlock(&lock);
    printf("Main finish1 \n");
    //pthread_exit(&cid1);
    pthread_join(cid1, NULL);
    printf("Main finish2 \n");
    pthread_join(cid2, NULL);
    pthread_join(cid3, NULL);

    fclose(fwptr);
    return 0;
}

//TASK///////////////////
void *task(void *param)
{
    queue *ptr = (queue *)param;
    FILE *frptr = fopen("task_file", "r");
    if (frptr == NULL)
        printf("Reader File not opened");

    int burst;
    char data[15];
    // int i=0;
    int c = 1;
    while ((fscanf(frptr, "%s %d", data, &burst)) != EOF)
    {

        pthread_mutex_lock(&lock);
        if (((ptr->head + 1) % ptr->buffsize) == ptr->tail) //adding remainder here too
        {                                                   //check full condition
            printf("full and Writer waiting\n");
            pthread_cond_wait(&not_full, &lock);
        }

        ptr->buffer[ptr->head] = burst;              //write burst time in buffer
        ptr->head = (ptr->head + 1) % ptr->buffsize; // for ring queue

        printf("Tasker Writes data : %s   %d \n", data, burst);
        fprintf(fwptr, "Tasker is Writing : %s %d \n", data, burst);
        if (burst == 20)
            ptr->state = 1;

        pthread_mutex_unlock(&lock);
        pthread_cond_broadcast(&not_empty);
        //sleep(0.25);
        c++;
    }
    printf("End of file");
    tasker = 1;
    fclose(frptr);
    pthread_exit(0);
}

//CPU////////////////
void *cpu(void *param)
{
    queue *ptr = (queue *)param;
    int bt, i = 0, j = 0;
    //sleep(1);
    for (;;)
    {
        pthread_mutex_lock(&lock);
        //printf("%s", tasker ? "true" : "false");

        if (ptr->head == ptr->tail)
        {                        //check empty condition
            if (ptr->state == 1) //if tasker finished
            {
                printf(" I quit");
                break;
            }
            printf("CPU head %d tail %d \n", ptr->head, ptr->tail);
            //printf("Tasker: %s \n",tasker?"TRUE":"FALSE" );
            printf("Tasker: %d \n", tasker);
            printf("CPU waiting \n");
            pthread_cond_wait(&not_empty, &lock);
        }
        if (ptr->head == ptr->tail)
        {                        //check empty condition
            if (ptr->state == 1) //if tasker finished
            {
                printf(" I quit");
                break;
            }
        }

        bt = ptr->buffer[ptr->tail];
        printf(" Execute blast time: %d \n", bt);

        //if ((ptr->head == ptr->tail) && (tasker == 1))
        //{ //check empty condition
        //ptr->state=1;
        //}
        // printf("CPU head %d tail %d \n",ptr->head,ptr->tail );
        fprintf(fwptr, "CPU is Writing : %d \n", bt);
        ptr->tail = (ptr->tail + 1) % ptr->buffsize;
        //printf("CPU waiting \n" );
        //if (ptr->state = 1) break;
        //printf("CPU waiting1 \n" );
        pthread_mutex_unlock(&lock);
        //printf("CPU waiting2 \n" );
        pthread_cond_signal(&not_full);
        //printf("CPU waiting3 \n" );
    }
    printf("I broke \n");
    //pthread_cancel(pthread_self());
    pthread_exit(0);
}
答案

几乎没有问题。

  1. 你应该用锁定互斥锁的pthread_cond_signal()pthread_cond_broadcast()。目前它们不在互斥体之内。
  2. 您应该在断开cpu()中的循环之前解锁互斥锁。 if (ptr->state == 1) //if tasker finished { printf(" I quit"); pthread_mutex_unlock(&lock); //Unlock break; }

我认为#2是真正的问题。其中一个CPU线程正在退出,互斥锁被锁定,另一个线程正在等待互斥锁永远。

更新您正在跨两个CPU线程共享资源。目前,对于每个数据产生,制作者正在广播。这可能会导致一些问题,因为您的数据消费代码不在if (ptr->head != ptr->tail)下我认为,您应该再做两次更改才能正常工作。

  1. 在生产者函数(task())中,你不应该使用pthread_cond_broadcast()但是使用pthread_cond_signal()。但是最后,即当ptr->state为1时,您可以根据需要进行广播以解除所有线程的阻塞。
  2. 在消费者函数(cpu())中,将消费部分放在if (ptr->head != ptr->tail)中,如下所示。

一个

   if (ptr->head == ptr->tail)
    {                        //check empty condition
        if (ptr->state == 1) //if tasker finished
        {
            //unlock mutex and break
        }
        //Wait for signal
    }

    if (ptr->head == ptr->tail)
    {                        //check empty condition
        if (ptr->state == 1) //if tasker finished
        {
            //unlock mutex and break
        }
    }
    else
    {
        bt = ptr->buffer[ptr->tail];
        //Rest of the consumption code
        ...
    }

以上是关于一些提示,以避免在这个pthreaded C程序中出现死锁的主要内容,如果未能解决你的问题,请参考以下文章

以非常低的优先级运行线程

Pthread C 同步

NSOperationQueue 与 pthread 优先级

C:更新共享内存 pthread 并使用 strncpy

从pthread中获得tid及pthread_mutex_unlock本身用户态互斥

这个C语言 啥意思啊#include <pthread.h>