如何使循环队列具有线程安全性?

3

以下是我的 Enqueue 和 Dequeue 函数。如何使它们线程安全?我考虑过使用来自 Windows.h 的互斥量,但如果可能的话,我不想将程序限制为仅适用于 Windows。

void Queue::Enqueue(int num){
    //increase recorded size
    size++;
    //stick in num
    numbers[nextSpace] = num;
    //find the next available space
    nextSpace = (++nextSpace) % maxSize;
}

int Queue::Dequeue(){
    int temp;
    temp = items[curSpace];
    curSpace = (++curSpace) % maxSize;
    size--;
    return temp;
}

1
为什么要重复造轮子呢?使用Boost的lockfree::queue或类似的东西吧。(或者如果你想要一个只有一个消费者和一个生产者的循环缓冲区,可以使用spsc_queue。) - Kerrek SB
Boost有一个用于同步的可移植库。请参见http://www.boost.org/doc/libs/1_53_0/doc/html/thread/synchronization.html。 - Jeff Paquette
你需要哪个版本的“线程安全”?STL是线程安全的,你知道吗? - Alex Chamberlain
1
谷歌搜索“无锁队列”。 - n. m.
你的Dequeue()操作没有测试空队列。你需要测试空队列并返回错误值,或者阻塞等待其他人执行下一个Enqueue()操作。如果你可以接受返回错误值(然后浪费CPU重复自旋),可以查看boost的无锁队列。如果你想要一个阻塞的Dequeue操作,请参考这个stackoverflow问题这个网站 - Wandering Logic
显示剩余3条评论
1个回答

0
您可以参考以下使用pthread的代码:
#include<pthread.h> 
#define DEFAULT_SIZE 100
class circularQueue{
 private:
    int *m_queue;
    int p_head;
    int p_tail;
    int m_cap;
    pthread_mutex_t mp = PTHREAD_MUTEX_INITIALIZER; 
    public:
        circularQueue(int size)
        {
            /*in case invalid input*/
            if(size<0)
                size = DEFAULT_SIZE ;

            m_queue = new int[size];
            p_head = 0;
            p_tail = -1;
            m_cap = 0;
            pthread_mutex_init(&mp,NULL);
        }

        bool enqueue(int x)
        {
            bool res= false;
            p_thread_mutex_lock(&mp);
            /*queue is full*/
            if(m_cap == size)
            {
                res = false;
            }
            else
            {
                m_queue[(++p_tail)%size)] = x;
                ++m_cap;
                res = true;
            }
            p_thread_mutex_unlock(&mp);
            return res;
        }
        int dequeue()
        {
            int res=0;

            pthread_mutex_lock(&mp);
            /*empty queue*/
            if(m_cap == 0)
            {    
                throw("empty queue!");
                pthread_mutex_unlock(&mp);
            }
            else{
                res = m_queue[p_head];    
                p_head = (p_head+1)%size;
            }
            pthread_mutex_unlock(&mp);
            return res;
        }    
        ~virtual circularQueue()
        {
            delete[] m_queue;
            m_queue = NULL;
            pthread_mutex_destroy(&mp);
        }
}

throw("empty queue!"); 语句使得这段代码具有死锁的能力(一个线程可以在锁定互斥量后抛出异常而不解锁)。即使这个问题被修复了,你仍然需要考虑到如果适用于非内置类型,其赋值可能会抛出异常,那么你就会遇到同样的问题。 - Mark B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接