QSemaphore是否足以制作QQueue的线程安全模拟

Is QSemaphore enough to make a thread safe analogue of QQueue?

本文关键字:线程 安全 模拟 QQueue 是否 QSemaphore      更新时间:2023-10-16

我试图对QQueue进行基本的线程安全模拟。这个想法是一个线程将数据放入队列,另一个线程处理它。我已经找到了一个非常基本的解决方案。

#include <QThread>
#include <QQueue>
#include <QSemaphore>
class AsyncQueue
{
public:
void enqueue(const int x);
int dequeue();
private:
QQueue<int> queue;
QSemaphore semaphore;
};
int AsyncQueue::dequeue()
{
semaphore.acquire();
return queue.dequeue();
}
void AsyncQueue::enqueue(const int x)
{
queue.enqueue(x);
semaphore.release();
return;
}

我是多线程的新手。它通过了一些最简单的测试,但我想知道这是否足够?或者队列是否需要AtomicPointer,以防线程在处理队列的最后一个项目时尝试将新项目排入队列?

事实并非如此,因为没有关键部分保护enqueue()对队列的写访问,因此有机会对队列进行并发读/写访问。它总是可以执行,因为QSemaphore::release()永远不会阻塞。因此,dequeue()enqueue(int)有很多机会同时执行,造成严重破坏。

您现在拥有的信号量完成了向队列的使用者端发送队列中存在的值的数量的信号的角色。您将需要第二个QSemaphore来实现对底层QQueue的独占访问,如下所示(经过非常肤浅的测试(:

#include <QThread>
#include <QQueue>
#include <QSemaphore>
class AsyncQueue
{
public:
void enqueue(const int x);
int dequeue();
private:
QQueue<int> queue;
QSemaphore itemsInQueue;
QSemaphore exclusiveAccess{1};
};
int AsyncQueue::dequeue()
{
itemsInQueue.acquire();
exclusiveAccess.acquire();
int result{queue.dequeue()};
exclusiveAccess.release();
return result;
}
void AsyncQueue::enqueue(const int x)
{
exclusiveAccess.acquire();
queue.enqueue(x);
exclusiveAccess.release();
itemsInQueue.release();
}

如果您可以使用现代编译器,我更喜欢使用STL对应程序来实现这一点。std::threadstd::mutexstd::lock_guardstd::condition_variable在这种情况下值得研究。

我认为您可以按照下面的说明进行尝试。

基本上文件上写着:

QSharedPointer和QWeakPointer是线程安全的,并且以原子方式操作指针值。不同的线程也可以访问同时指向同一对象的QSharedPointer或QWeakPointer时间而不需要锁定机制。

因此您不需要锁定机制。。。。。

如何:

using sInt = QSharedPointer<int>;
QQueue<sInt> qInt; //Your queue of shared pointer objects.
qInt.enqueue(QSharedPointer<int>::create(5));
qInt.enqueue(QSharedPointer<int>::create(6));
qInt.enqueue(QSharedPointer<int>::create(7));
qInt.enqueue(QSharedPointer<int>::create(8));
//To retrieve the value use either data() or get() as shown below.
sInt value =  qInt.dequeue();
int *val = value.data();