【问题标题】:How do I make a circular queue thread-safe?如何使循环队列线程安全?
【发布时间】:2013-03-22 23:56:39
【问题描述】:

所以我的入队和出队函数如下。如何获取我拥有的东西并使其线程安全?我曾考虑使用 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;
}

【问题讨论】:

  • 为什么要重新发明轮子?使用 Boost 的 lockfree::queue 或类似的东西。 (或者spsc_queue,如果你想为一个消费者和一个生产者提供一个循环缓冲区。)
  • Boost 有一个用于同步的可移植库。见boost.org/doc/libs/1_53_0/doc/html/thread/synchronization.html
  • 您需要什么版本的“线程安全”? STL 是线程安全的,你知道吗?
  • 谷歌搜索“无锁队列”
  • 您的 Dequeue() 操作不会测试空队列。您需要测试空队列并返回错误值,或者阻止等待其他人执行下一个 Enqueue()。如果您可以返回错误值(然后通过重复旋转浪费 CPU)查看 boost 的无锁队列。如果您想要阻塞出队操作,请参阅this stack overflow questionthis web site

标签: c++ multithreading queue


【解决方案1】:

您可以参考此代码(使用 pthreads):

#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!"); 使此代码具有死锁能力(线程可以锁定互斥体,然后在不解锁的情况下抛出)。即使这已解决,您仍然必须考虑,如果适应非内置类型,其分配可能会引发同样的问题。
猜你喜欢
  • 2018-04-01
  • 2018-08-15
  • 1970-01-01
  • 2014-12-14
  • 2012-05-30
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 2013-02-23
相关资源
最近更新 更多