c++ - Qt Blocking Master 示例中 Mutex 的使用

标签 c++ multithreading qt serial-communication

我正在研究 Qt Blocking Master example了解使用 Qt 进行串行通信。在此示例中,串行通信以同步方式完成,因此,为了保持 GUI 响应,创建了一个单独的(非 GUI)线程来处理串行通信。我不明白的是在负责通信的线程(即MasterThread)中使用互斥锁来同步线程的部分:

Note, the transaction() method is called in the main thread, but the request is provided in the MasterThread thread. The MasterThread data members are read and written concurrently in different threads, thus the QMutex class is used to synchronize the access.

void MasterThread::transaction(const QString &portName, int waitTimeout, const QString &request)
{
    QMutexLocker locker(&mutex);
    this->portName = portName;
    this->waitTimeout = waitTimeout;
    this->request = request;
    if (!isRunning())
        start();
    else
        cond.wakeOne();
}

[MasterThread run method]

void MasterThread::run()
{
    bool currentPortNameChanged = false;

    mutex.lock();
QString currentPortName;
if (currentPortName != portName) {
    currentPortName = portName;
    currentPortNameChanged = true;
}

int currentWaitTimeout = waitTimeout;
QString currentRequest = request;
mutex.unlock();

Under no circumstance should the transaction() method be called simultaneously with a process fetching the data. Note, while the QString class is reentrant, it is not thread-safe. Thereby, it is not recommended to read the serial port name in a request thread, and timeout or request data in another thread. The MasterThread class can only handle one request at a time.

我的问题:

  1. 我不明白 Mutex 的必要性。我的理由是只有一个线程(在Dialog 类中创建)处理通信,因此不存在竞争条件,也不需要同步。

  2. 我对上面引用的最后一句话(即“在任何情况下……”)更加困惑。 “[另一个] 进程获取数据”是什么意思?我们这里不是只有一个进程(即整个应用程序)和两个线程(一个用于 GUI,一个用于串行通信)并且这两个线程没有共享数据吗?为什么 QString 的线程安全在这里很重要?

最佳答案

I don't understand the need for Mutex. My reasoning is that there is only one thread (created in the Dialog class) that handles the communication and therefore there is no race condition and no need for synchronization.

应用程序从一个已经激活的线程开始。那是gui线程。一旦您启动其他线程,就会有多个 线程。如果与其他线程隔离,通信线程将毫无用处。一旦不再隔离,就需要一种同步访问共享数据的方法,并且必须共享一些数据——这就是没有隔离的定义。解除线程隔离的唯一方法是共享一些数据(如果操作系统或硬件可能提供的低级消息传递功能未被使用 - 在这里,它不是)。

同步是在 gui 线程和通信线程之间进行的。 transaction() 方法必须是线程安全的,即它必须使用一些同步原语 - 这里是互斥体。

What does "[another] process fetching the data" mean?

进程在特定句子中用作线程的不幸同义词。

why does the thread safety of QString matter here

QString 的线程安全很重要,因为特定的QString 实例一次只能从一个线程访问,即不支持并发。甚至不支持读取并发 - 有些人认为只因为他们不修改数据,只读访问是线程安全的。除非明确指定,否则不会。具体在这种情况下:在线程 1 中读取给定的 QString,并在线程 2 中写入它,会导致未定义的行为,这不是假设。你会腐败的东西。

these two threads don't have shared data

一个进程的线程都在同一个地址空间,因此默认共享数据。因此需要同步原语。同步可以是隐式的,例如如果线程通过发布事件进行通信,则事件队列是同步原语:它序列化从事件发布者到事件接收者的访问,即针对给定线程的事件发布者同步到该线程中的接收者。

关于c++ - Qt Blocking Master 示例中 Mutex 的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50905338/

相关文章:

c++ - QT - 拖放 - 在拖放位置的自定义场景上创建自定义图形对象

c++ - 在 QTextEdit 中对齐文本?

c++ - C++ 17 可以处理嵌套的可变参数模板吗?

c++ - 在 C++ 中使用 auto 作为我的函数的返回值在 CodeBlocks 中不起作用

multithreading - 如何在 Go 中手动创建线程?

java - 如何轮流监听两组线程获取synchronized section?

visual-studio - Qt:我应该使用 Visual Studio、Qt Creator 还是其他东西?

从 Windows 而不是从 Visual Studio 运行时,C#/C++ 应用程序崩溃

c++ - 检查树故障的算法

c - 使用专用线程进行文件输出