c - C 中的非忙阻塞队列实现

标签 c locking queue posix ibm-midrange

我正在尝试在 C 中实现一个队列,该队列会导致进程处于非繁忙状态,直到队列中有一个元素可供使用。我尝试了两种不同的方法来实现这一目标。

我遇到的第一个问题是,如果入队/出队操作有 if 条件来检查边界( if(q->count == QUEUESIZE) ),对 sem_wait 的调用将立即返回,因为没有其他进程获得锁。

如果我将条件更改为 while(q->count == QUEUESIZE),我相信消费者进程将“忙等待”,直到生产者进程发布信号量,这不是我的实现目标,通过测试,发现消费者进程不会获取锁并继续执行。

我认为我已经很接近了,但我似乎不知道如何解决这些问题。我考虑过添加条件变量或 pthread_mutex,但想在增加额外的复杂性之前耗尽信号量选项。

#define QUEUESIZE 48

typedef struct 
{           
    char q[QUEUESIZE+1][150];
    int first;                      
    int last;                       
    int count;                      
    sem_t *lock;                    
} Queue;


init_queue(Queue *q, sem_t *l)
{
    q->first = 0;
    q->last = QUEUESIZE-1;
    q->count = 0;
    q->lock = l;
}

enqueue(Queue *q, char x[150])
{
    while(q->count == QUEUESIZE)
        sem_wait(q->lock);

    if (q->count == 0)
    {
        if (sem_post(q->lock) == -1)
        {
            printf("Thread failed to unlock semaphore\n");
        }
    }       
    q->last = (q->last+1) % QUEUESIZE;
    strcpy(q->q[ q->last ],x);    
    q->count = q->count + 1;
}

dequeue(Queue *q,char *ptr)
{
    char x[150];
    while(q->count == 0)
        sem_wait(q->lock);

    if (q->count == QUEUESIZE) 
    {
        if (sem_post(q->lock) == -1)
        {
            printf("Thread failed to unlock semaphore\n");
        }
    }   
    strcpy(ptr,q->q[ q->first]);
    q->first = (q->first+1) % QUEUESIZE;
    q->count = q->count - 1;
}

最佳答案

根据要求,这是我的解决方案。

#define QUEUESIZE 50

typedef struct 
{           
    char q[QUEUESIZE][150];
    int first;                      
    int last;                       
    int count;                      
    sem_t *full;
    sem_t *empty;
    sem_t *excl;

} Queue;


void init_queue(Queue *q, sem_t *f,sem_t *e, sem_t *ee,)
{
    q->first = 0;
    q->last = QUEUESIZE-1;
    q->count = 0;
    q->full = f;
    q->empty = e;
    q->excl = ee; 
}

void enqueue(Queue *q, char x[150])
{
    sem_wait(q->empty);
    sem_wait(q->excl);

    q->last = (q->last+1) % QUEUESIZE;
    strcpy(q->q[ q->last ],x);    
    q->count = q->count + 1;

    sem_post(q->excl);
    sem_post(q->full);
}

void dequeue(Queue *q,char *ptr)
{
    sem_wait(q->full);
    sem_wait(q->excl);

    strcpy(ptr,q->q[ q->first]);
    q->first = (q->first+1) % QUEUESIZE;
    q->count = q->count - 1;

    sem_post(q->excl);
    sem_post(q->empty);
}

我按如下方式初始化信号量:

sem_init(full,1,0);
sem_init(empty,1,49);
sem_init(dequeue_excl,1,1);
sem_init(enqueue_excl,1,1);

关于c - C 中的非忙阻塞队列实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16239864/

相关文章:

C 程序比较两个大小不等的数组

C - Return 语句不退出 void 函数

php - 我如何很好地解码 Laravel 失败的作业 JSON

sql-server - 从 SQL Server 数据库获取 "next"行并在单个事务中标记它

c - 返回伪随机数-C 编程语言

c - C 中的 stdbool.h bool 类型按位异或 ^ 和赋值

java - 如何使用锁来确保一个方法只能同时运行一定次数

java - 是否可以显式使用 Java 内在锁?

c - 等待/ sleep ,直到远程文件在 c 中解锁

concurrency - 如何实现 pop -> 做一些事情 -> 使用 goroutines 推送队列