我是信号量的新手,想知道如何避免我的工作线程(在多个工人单一生产者问题中)卡在sem_wait(&full)
中的情况。在此之后我也有一个互斥锁,但我怀疑,这就是卡住的地方。我知道我的所有任务都已完成,但线程没有退出。所有任务完成后,程序中的生产者线程停止发送数据。
供参考......生产者线程......
while (i<number_of_tasks)
{
TASK task;
task.start_row = i*num_of_rows;
task.num_of_rows = num_of_rows;
sem_wait(&empty);
pthread_mutex_lock(&mutex);
tasks[in] = task;
in = (in+1)%buff_size;
pthread_mutex_unlock(&mutex);
sem_post(&full);
i++;
//printf("%d tasks completed out of %d tasks\n", counter, number_of_tasks);
if (counter==number_of_tasks)
break;
}
并且......工作线程函数
int i, item, index;
TASK task;
index = *((int*)arg);
int notasks1;
for (i=number_of_tasks; i > 0; i--) {
//previous code
sem_wait(&full);
pthread_mutex_lock(&mutex);
task=tasks[out];
out = (out+1)%buff_size;
//completing task code...
counter++;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
printf("%d tasks completed out of %d tasks\n", counter, number_of_tasks);
if (counter==number_of_tasks)
break;
}
printf("Worker thread %d has terminated and completed %d tasks\n",index,notasks1);
return NULL;
完整代码......供参考
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include </usr/include/semaphore.h>
// for sleep
#include <unistd.h>
#include "Mandel.h"
#include "draw.h"
#define BUFF_SIZE 10 /* total number of slots */
#define NP 1 /* total number of producers */
#define NC 5 /* total number of consumers */
#define NITERS IMAGE_HEIGHT/10 /* number of items produced/consumed */
//int buf[BUFF_SIZE]; /* shared var */
//struct task for storing the tasks the current worker thread has to do
typedef struct task
{
int start_row;
int num_of_rows;
} TASK;
TASK* tasks;
int buff_size; //= 7;
//TASK buff[buff_size];
int in=0; /* buf[in%BUFF_SIZE] is the first empty slot */
int out=0; /* buf[out%BUFF_SIZE] is the first full slot */
sem_t full; /* keep track of the number of full spots */
sem_t empty; /* keep track of the number of empty spots */
int number_of_tasks;// = IMAGE_HEIGHT/20;
float *pixels;
int num_of_rows;// = 20;
int counter = 0;
// use correct type here
pthread_mutex_t mutex; /* enforce mutual exclusion to shared data */
/*void *Producer(void *arg)
{
int i =0;
while (i<number_of_tasks)
{
if (counter==number_of_tasks)
break;
TASK task;
task.start_row = i*num_of_rows;
task.num_of_rows = num_of_rows;
sem_wait(&empty);
pthread_mutex_lock(&mutex);
tasks[in] = task;
in = (in+1)%buff_size;
pthread_mutex_unlock(&mutex);
sem_post(&full);
i++;
if (counter==number_of_tasks)
break;
}
return NULL;
}*/
//function for consumer threads to accesss
void *Consumer(void *arg)
{
int i, item, index;
TASK task;
index = *((int*)arg);//getting index of thread from argument parsing it into int
int notasks1;
//for loop to complete number of tasks per thread
for (i=number_of_tasks; i > 0; i--) {
//defining start_compute and end compute to calculate time per task
struct timespec start_compute, end_compute;
float difftime;
printf("Worker(%d): Start the computation ...\n", index);
clock_gettime(CLOCK_MONOTONIC, &start_compute);
//calling sem wait to wait for producer thread to fill in tasks for worker threads. will wait if buffer is empty
sem_wait(&full);
//calling mutex lock
pthread_mutex_lock(&mutex);
//getting tasks from struct tasks array
task=tasks[out];
//incrementing to next task in buffer so that next thread accesses next task
out = (out+1)%buff_size;
//calculating pixels for image
int x, y;
//printf("start_row... %d, num_of_rows... %d\n", task.start_row, task.num_of_rows);
for (y=task.start_row; y<task.start_row+task.num_of_rows; y++)
{
for (x=0; x<IMAGE_WIDTH; x++)
{
pixels[y*IMAGE_WIDTH+x] = Mandelbrot(x, y);
}
}
//increasing counter to check if all tasks are done
counter++;
pthread_mutex_unlock(&mutex);
sem_post(&empty);//informing a producer that a task has been taken out and if tasks are left buffer is empty to add tasks
//calculating end compute and posting
clock_gettime(CLOCK_MONOTONIC, &end_compute); //end time values for the child processes
difftime = (end_compute.tv_nsec - start_compute.tv_nsec)/1000000.0 + (end_compute.tv_sec - start_compute.tv_sec)*1000.0;
printf("Worker(%d):\t...completed. Elapse time = %f ms\n",index, difftime);\
notasks1++;
printf("%d tasks completed out of %d tasks\n", counter, number_of_tasks);
if (counter==number_of_tasks)
break;
}
printf("Worker thread %d has terminated and completed %d tasks\n",index,notasks1);
return NULL;
}
int main(int argc, char* args[])
{
buff_size = atoi(args[3]);
num_of_rows = atoi(args[2]);
number_of_tasks = IMAGE_HEIGHT/num_of_rows;
int number_of_workers;
number_of_workers = atoi(args[1]);
struct timespec start_time, end_time;
printf("number_of_tasks...%d\n", number_of_tasks);
pthread_t idP, idC;
int index;
sem_init(&full, 0, 0);//initializing full to zero so that consumer thread knows buffer is empty and waits for producer thread
sem_init(&empty, 0, buff_size);//initializing empty to buffer size so that producer knows to add that many tasks
pthread_mutex_init(&mutex, NULL);
int i = 0;
pixels = (float *) malloc(sizeof(float) * IMAGE_WIDTH * IMAGE_HEIGHT);//assigning pixels memory
//tasks = (TASK*) malloc (sizeof(TASK) *buff_size);
//pthread_create(&idP, NULL, Producer, NULL);
for(index=0; index<number_of_workers/*5*/; index++)
{
printf("Worker(%d): Start up. Wait for task!\n", index);
pthread_create(&idC, NULL, Consumer, (void*)&index);//creating worker threads to go to consumer function sending their index
}
tasks = (TASK*) malloc (sizeof(TASK) *buff_size);
//master/producer thread work
while (i<number_of_tasks)
{
TASK task;
task.start_row = i*num_of_rows;
task.num_of_rows = num_of_rows;
//calling sem wait if buffer is not empty
sem_wait(&empty);
pthread_mutex_lock(&mutex);
//adding tasks to struct task tasks array for worker/consumer threads to use
tasks[in] = task;
in = (in+1)%buff_size;
pthread_mutex_unlock(&mutex);
sem_post(&full);
//incrementing full so that worker threads know that buffer is not empty
i++;
//printf("%d tasks completed out of %d tasks\n", counter, number_of_tasks);
if (counter==number_of_tasks)
break;
}
//pthread_exit(NULL);
//waiting for all threads to exit
//pthread_join(idC, NULL);
//printing image
printf("Draw the image\n");
DrawImage(pixels, IMAGE_WIDTH, IMAGE_HEIGHT, "Mandelbrot demo", 3000);
return 0;
}
如何阻止工作线程卡在循环中?
我知道程序会继续并显示正确的结果但是当我打电话给pthread_join
时,它会继续等待......显然。如何解决这个问题?