一些提示,以避免在这个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(¬_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(¬_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(¬_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(¬_full);
//printf("CPU waiting3 \n" );
}
printf("I broke \n");
//pthread_cancel(pthread_self());
pthread_exit(0);
}
答案
几乎没有问题。
- 你应该用锁定互斥锁的
pthread_cond_signal()
和pthread_cond_broadcast()
。目前它们不在互斥体之内。 - 您应该在断开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)
下我认为,您应该再做两次更改才能正常工作。
- 在生产者函数(
task()
)中,你不应该使用pthread_cond_broadcast()
但是使用pthread_cond_signal()
。但是最后,即当ptr->state
为1时,您可以根据需要进行广播以解除所有线程的阻塞。 - 在消费者函数(
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程序中出现死锁的主要内容,如果未能解决你的问题,请参考以下文章
NSOperationQueue 与 pthread 优先级