在不同线程中同步数据访问

时间:2013-11-07 12:48:25

标签: multithreading qt

我有一个工作线程,它通过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()

     

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

我有两个问题:

  1. 在不同的帖子中解锁这种限制的原因是什么? (为什么我没有看到医生说的错误?)

  2. 我应该使用什么而不是QMutex来实现我的目标? QWaitCondition是否足以取代?

1 个答案:

答案 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