简体   繁体   English

如何使队列线程安全

[英]How to make a queue thread-safe

Two threads working on this queue at the same time could make it fail. 同时在此队列上工作的两个线程可能会使它失败。 What will you do to make concurrent accesses work correctly? 您将如何使并发访问正常工作? Should the queue make the threads wait if they try to remove an element from an empty queue or add one to a full one? 如果线程尝试从一个空队列中删除一个元素或将一个元素添加到一个完整的队列中,则该队列应该让线程等待吗?

#include <stdlib.h>

// circular array
typedef struct _queue {
    int size;
    int used;
    int first;
    void **data;
} _queue;

#include "queue.h"

queue q_create(int size) {
    queue q = malloc(sizeof(_queue));

    q->size  = size;
    q->used  = 0;
    q->first = 0;
    q->data = malloc(size*sizeof(void *));

    return q;
}

int q_elements(queue q) {
    return q->used;
}

int q_insert(queue q, void *elem) {
    if(q->size==q->used) return 0;

    q->data[(q->first+q->used) % q->size] = elem;    
    q->used++;

    return 1;
}

void *q_remove(queue q) {
    void *res;
    if(q->used==0) return NULL;

    res=q->data[q->first];

    q->first=(q->first+1) % q->size;
    q->used--;

    return res;
}

void q_destroy(queue q) {
    free(q->data);
    free(q);
}

The objective of this queue is to manage the input and output of the compression tool I'm trying to develop. 该队列的目的是管理我要开发的压缩工具的输入和输出。

Thread safe means that you have to isolate any shared data.Here your shared data is the pointer to the queue.So , in general , any time you have operations on the queue you need to protect queue and prevent multiple threads reach your queue at the same time.One good way is to implement Condition Variables. 线程安全意味着您必须隔离所有共享数据。这里的共享数据是指向队列的指针。因此,通常,任何时候只要对队列执行操作,就需要保护队列并防止多个线程到达队列。同时,一种好方法是实现条件变量。 Variables are switches to lock threads in crucial data. 变量是将线程锁定在关键数据中的开关。

I can't see the thread code here. 我在这里看不到线程代码。 So , let's assume you have a thread that writes in a queue. 因此,假设您有一个写入队列的线程。 First you have to declare Condition Variables. 首先,您必须声明条件变量。

#include <pthread.h>


pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t w_condition = PTHREAD_COND_INITIALIZER;

que_state_t que_write_state = READY;  //this is just an enum


void* writer_thread_v2(void* t)
{
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
    int i = 0;
    while ( 1 )
    {
        pthread_mutex_lock(&mutex2);    
        while( que_write_state == NOT_READY )
        {
            pthread_cond_wait(&w_condition , &mutex2);
        }
        que_write_state = NOT_READY;
        person_t* doe = NULL;
        pthread_cleanup_push(clean_memory2, &doe);
        doe = (person_t*) malloc(sizeof(person_t));

        person_t static_person = random_person();
        doe->age_bracket = static_person.age_bracket;
        memcpy(doe->name , static_person.name , NAME_LENGTH);
        push(the_queue , doe );
        pthread_cleanup_pop(0);

        que_write_state = READY;
        pthread_mutex_unlock(&mutex2);
        pthread_cond_signal(&w_condition);
        i++;
    }
    pthread_exit(0);
}

Here the thread enters a while loop. 在这里线程进入while循环。

    pthread_mutex_lock(&mutex2);    //Here puts a lock on mutex    
    while( que_write_state == NOT_READY )    //Here checks the enum
    {
        pthread_cond_wait(&w_condition , &mutex2);
    }
    que_write_state = NOT_READY;      //Here puts the enum in not ready mode

Now all threads of this kind are going to stop and wait until the queue operations finish and you release the mutex. 现在,所有此类线程都将停止并等待队列操作完成并释放互斥量。 A big memory leak problem comes here.What if a thread creates an object and it is cancelled before add data in queue.This is why in the code there is 这里出现一个大的内存泄漏问题。如果线程创建了一个对象并在添加数据到队列中之前取消了该对象怎么办,这就是为什么在代码中存在

pthread_cleanup_push(clean_memory2, &doe);
{
    inside here it mallocs the heap memory it is needed and adds data in 
    queue.If at any time the thread is cancelled clean_memory2() is called 
    which frees doe.
}
pthread_cleanup_pop(0);

pthread_cleanup_push is going to protect you for memory leaks while creating the object you want to store , and complete the import procedure.Cleanup_push (ghost block) stops at cleanup switch. pthread_cleanup_push将在创建要存储的对象时保护您避免内存泄漏,并完成导入过程。Cleanup_push(ghost块)在清理开关处停止。 After push in que this thread is going to release mutex and sends a signal to the rest of the Threads waiting. 推入队列后,该线程将释放互斥锁,并向等待的其他线程发送信号。

    que_write_state = READY;   //here sets switch to ready mode
    pthread_mutex_unlock(&mutex2);   //unlocks mutex

    pthread_cond_signal(&w_condition); //signal the next one.

Thank you. 谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM