在 C# 中,如果我有例如我可以做的列表
lock (this.mylist)
{
...
}
并且使用该代码,我确信在释放锁定之前没有其他人可以使用该列表。这在多线程应用程序中很有用。我怎样才能在 Qt 上做同样的事情?我阅读了有关 QMutex 和 QReadWriteLock 的文档,但我不明白如何在特定对象上使用它们。
要使用QMutex
(或 C/C++ 中的任何标准同步方法),所有相互依赖的关键部分都必须了解互斥锁。确保这一点的最简单(但不是 C++ 中的最佳实践,即使其成为类成员或其他东西)方法是创建一个全局变量互斥锁(例如,我们将这样做)。
所以考虑以下
QMutex mutex;
void someMethod()
{
mutex.lock();
// Critical section
mutex.unlock();
}
现在,lock
和unlock
是原子方法,因此在任何给定时间只有一个线程能够进入临界区。关键是两者都试图访问同一个互斥锁。
因此,本质上,这与C#
您需要自己管理互斥锁的方式相同。所以lock(...) { ... }
块被替换为mutex.lock() ... mutex.unlock()
. 然而,这也意味着,无论何时您想要访问关键部分项目(即在您的示例中this->mylist
),您都应该使用互斥锁。
编辑
Qt 有很好的文档。您可以在此处阅读更多信息:http QMutex
: //doc.qt.io/qt-4.8/qmutex.html
执行此类操作的一般 C++ 方法是使用 RAII,因此您最终会得到如下代码:
// Inside a function, a block that needs to be locked
{
QMutexLocker lock(&mutex); // locks mutex
// Do stuff
// "QMutexLocker" destructor unlocks the mutex when it goes out of scope
}
我不知道这如何转化为 Qt,但如果没有本机支持,您可能会编写一个帮助程序类。
编辑:感谢 Cory,您可以看到 Qt 非常好地支持这个习语。
在 C++11 中,您可以这样做:
#include <thread>
#include <mutex>
std::mutex mut;
void someMethod()
{
std::lock_guard(mut);
// Critical section
}
这是 RAII 惯用语 - 锁守卫是一个无论 someMethod 范围如何退出(正常返回或抛出)都会释放锁的对象。请参阅 Anthony Williams 的 C++ concurrency In Action。他还有一个C++11 线程实现。C++11 的实现很像 boost 线程的实现。