线程安全队列有问题吗? [英] Problem with thread-safe queue?
问题描述
我正在尝试使用c ++中的pthreads编写线程安全队列.我的程序有93%的时间有效.其他时间中,有7%的时间会吐出垃圾,或者似乎睡着了.我想知道队列中是否有上下文切换会破坏它的缺陷?
I'm trying to write a thread-safe queue using pthreads in c++. My program works 93% of the time. The other 7% of the time it other spits out garbage, OR seems to fall asleep. I'm wondering if there is some flaw in my queue where a context-switch would break it?
// thread-safe queue
// inspired by http://msmvps.com/blogs/vandooren/archive/2007/01/05/creating-a-thread-safe-producer-consumer-queue-in-c-without-using-locks.aspx
// only works with one producer and one consumer
#include <pthread.h>
#include <exception>
template<class T>
class tsqueue
{
private:
volatile int m_ReadIndex, m_WriteIndex;
volatile T *m_Data;
volatile bool m_Done;
const int m_Size;
pthread_mutex_t m_ReadMutex, m_WriteMutex;
pthread_cond_t m_ReadCond, m_WriteCond;
public:
tsqueue(const int &size);
~tsqueue();
void push(const T &elem);
T pop();
void terminate();
bool isDone() const;
};
template <class T>
tsqueue<T>::tsqueue(const int &size) : m_ReadIndex(0), m_WriteIndex(0), m_Size(size), m_Done(false) {
m_Data = new T[size];
pthread_mutex_init(&m_ReadMutex, NULL);
pthread_mutex_init(&m_WriteMutex, NULL);
pthread_cond_init(&m_WriteCond, NULL);
pthread_cond_init(&m_WriteCond, NULL);
}
template <class T>
tsqueue<T>::~tsqueue() {
delete[] m_Data;
pthread_mutex_destroy(&m_ReadMutex);
pthread_mutex_destroy(&m_WriteMutex);
pthread_cond_destroy(&m_ReadCond);
pthread_cond_destroy(&m_WriteCond);
}
template <class T>
void tsqueue<T>::push(const T &elem) {
int next = (m_WriteIndex + 1) % m_Size;
if(next == m_ReadIndex) {
pthread_mutex_lock(&m_WriteMutex);
pthread_cond_wait(&m_WriteCond, &m_WriteMutex);
pthread_mutex_unlock(&m_WriteMutex);
}
m_Data[m_WriteIndex] = elem;
m_WriteIndex = next;
pthread_cond_signal(&m_ReadCond);
}
template <class T>
T tsqueue<T>::pop() {
if(m_ReadIndex == m_WriteIndex) {
pthread_mutex_lock(&m_ReadMutex);
pthread_cond_wait(&m_ReadCond, &m_ReadMutex);
pthread_mutex_unlock(&m_ReadMutex);
if(m_Done && m_ReadIndex == m_WriteIndex) throw "queue empty and terminated";
}
int next = (m_ReadIndex +1) % m_Size;
T elem = m_Data[m_ReadIndex];
m_ReadIndex = next;
pthread_cond_signal(&m_WriteCond);
return elem;
}
template <class T>
void tsqueue<T>::terminate() {
m_Done = true;
pthread_cond_signal(&m_ReadCond);
}
template <class T>
bool tsqueue<T>::isDone() const {
return (m_Done && m_ReadIndex == m_WriteIndex);
}
可以这样使用:
// thread 1
while(cin.get(c)) {
queue1.push(c);
}
queue1.terminate();
// thread 2
while(!queue1.isDone()) {
try{ c = queue1.pop(); }
catch(char const* str){break;}
cout.put(c);
}
如果有人对此有疑问,请这么说:)
If anyone sees a problem with this, please say so :)
推荐答案
如果您想要任何性能都不错的产品,我强烈建议您放弃R/W锁,而只需使用一个非常简单的自旋锁即可.或者,如果您真的认为可以通过R/W锁定获得所需的性能,那么我会根据
If you want anything with decent performance I would strongly suggest dumping your R/W lock and just use a very simple spinlock. Or if you really think you can get the performance you want with R/W lock, i would roll your own based on this design(single word R/W Spinlock) from Joe Duffy.
这篇关于线程安全队列有问题吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!