Qt Blocking Master 示例中 Mutex 的使用

Use of Mutex in Qt Blocking Master example

我正在研究 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 class 中创建)处理通信,因此没有竞争条件,也不需要同步.

  2. 上面引用的最后一句话(即"Under no circumstance ...")让我更加困惑。 “[另一个] 进程获取数据”是什么意思?我们这里不是只有一个进程(即整个应用程序)和两个线程(一个用于 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线程。一旦您启动其他线程,就会有 多个 线程。如果与其他线程隔离,通信线程将毫无用处。一旦不再隔离,就需要一种同步访问共享数据的方法,并且必须共享一些数据——这就是没有隔离的定义。解除线程隔离的唯一方法是共享一些数据(如果 OS 或硬件可能提供的低级消息传递功能未被使用 - 在这里,它不是)。

同步是在 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

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