0

我有一个工作线程,它通过 TCP 发送一些数据,从其他几个线程中获取这些数据。我需要填充一些数据,在它上面有一个互斥锁,然后调用另一个线程的方法,然后在完成时解锁互斥锁,而调用者线程将继续自己的工作。

我首先使用 Qt 实现了这一点,如下所示:

Data globalData;
QMutex mutex;

void requestSend() // several such functions in other threads
{
    mutex.lock(); // we want to change the data
    globalData=fillData();
    invokeMethod(workerClass,"work",Qt::QueuedConnection);
}

void work() // a slot in a class instanced in worker thread
{
    sendData(globalData);
    mutex.unlock(); // data is now available to be changed
}

这似乎是合理的,甚至可行,但后来我在 QMutex 文档中发现了这一点:

无效 QMutex::unlock ()

解锁互斥锁。尝试在与锁定它的线程不同的线程中解锁互斥锁会导致错误。解锁未锁定的互斥锁会导致未定义的行为。

我有两个问题:

  1. 这种限制在不同线程中解锁的原因是什么?(为什么我看不到文档所说的错误?)

  2. 我应该用什么代替 QMutex 来实现我想要的?QWaitCondition 会是一个合适的替代品吗?

4

1 回答 1

1

互斥锁的目的是确保任何时候只有一个线程可以访问数据。因此,锁定一个线程并在另一个线程中解锁相同的互斥体并没有真正的意义。

如果您发现它有效,那么您现在可能只是幸运,但这并不意味着如果线程的时间发生变化它不会给您带来问题。

我不太确定您到底要做什么,但似乎您有各种线程可以写入 globalData 并且一旦写入它,您希望另一个线程在更多数据写入之前发送数据到全局数据。

我的建议是围绕数据的写入创建一个互斥体,然后调用一个信号将数据发送到将发送数据的线程。在不同的线程上,无论如何都会复制数据:-

void requestSend() // several such functions in other threads
{
    QMutexLocker locker(&mutex);
    globalData=fillData();
    emit SendData(globalData); // send signal to the thread which will send the data
}

请注意,QMutexLocker 用于确保释放锁,即使发生异常也是如此。

不要太在意信号和槽中数据的复制;Qt 非常高效,如果您使用它的容器对象,由于隐式共享,它只会创建“写入时复制” 。即使它必须制作副本以在线程之间传递数据,你也不应该真正担心它,除非你能看到性能问题。

最后,请注意,隐式共享和多线程可以愉快地一起工作,您可以在此处阅读

于 2013-11-07T13:23:56.020 回答