我有一个工作线程,它通过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文档中找到了这个:
void QMutex :: unlock()
解锁互斥锁。尝试在与锁定的线程不同的线程中解锁互斥锁 它会导致错误。解锁未锁定的互斥锁会导致未定义的行为。
我有两个问题:
在不同的帖子中解锁这种限制的原因是什么? (为什么我没有看到医生说的错误?)
我应该使用什么而不是QMutex来实现我的目标? QWaitCondition是否足以取代?
答案 0 :(得分:1)
互斥锁的目的是确保一次只有一个线程可以访问数据。因此,锁定一个线程并在另一个线程中解锁相同的互斥锁实际上没有意义。
如果你发现它有效,那么你现在可能只是幸运,但并不意味着如果线程的时间发生变化,它不会引起你的问题。
我不太确定你要做什么,但看起来你有各种各样的线程可以写入globalData,一旦你写入它,你想要另一个线程发送数据之前更多数据写入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是非常有效的,如果你使用它的容器对象,它只会创建一个“写入时复制”,由于implicit sharing。即使它必须制作用于在线程之间传递数据的副本,你也不应该担心它,除非你能看到性能问题。
最后,请注意隐式共享和多线程可以一起愉快地工作,read here。