【问题标题】:Qt5 QWaitCondition exampleQt5 QWaitCondition 示例
【发布时间】:2013-11-12 15:36:42
【问题描述】:

我正在熟悉 QT5 并发库。我正在查看 QWaitCondition 示例 (http://qt-project.org/doc/qt-5.0/qtcore/qwaitcondition.html#details)。
在这里,一个线程(线程 B)读取用户输入,所有其他线程(线程 A)处理此输入。

线程 A:

forever {
    mutex.lock();
    keyPressed.wait(&mutex);
    ++count;
    mutex.unlock();

    do_something();

    mutex.lock();
    --count;
    mutex.unlock();
}

线程 B:

forever {
    getchar();

    mutex.lock();
    // Sleep until there are no busy worker threads
    while (count > 0) {
        mutex.unlock();
        sleep(1);
        mutex.lock();
    }
    keyPressed.wakeAll();
    mutex.unlock();
}

使用计数变量和广泛的互斥同步的原因是为了防止符号丢失。
问题是,我认为符号仍有可能丢失: 想象以下场景:

  1. 线程 A 处理一个符号,并减少计数(--count); 互斥体被释放;然后线程 A 停止

  2. 线程 B 从睡眠中返回,获取互斥体,看到,计数 == 0,并调用 keyPressed.wakeAll(),然后解锁互斥锁。 然而,wakeAll() 调用无处可去,因为线程 A 是 不等。

  3. 线程 A 再次启动,获取互斥体并进入 wait()。 由于已经调用了 wakeAll(),因此符号丢失了。

我是对的,还是我错过了什么?如果我是对的,如何更正示例以真正防止它跳过符号?

【问题讨论】:

    标签: c++ multithreading qt


    【解决方案1】:

    你是对的

    要解决此问题,应使用已获取的互斥锁进入循环:

    mutex.lock();
    forever {
    
        keyPressed.wait(&mutex);
        ++count;
        mutex.unlock();
    
        do_something();
    
        mutex.lock();
        --count;
    
    }
    mutex.unlock();
    

    【讨论】:

    • 不幸的是,您的解决方案仍然无法修复它,因为keyPressed.wait() 在执行实际等待之前在内部释放了互斥锁。如果线程 A 在这一刻停止执行,那么线程 B 可能会利用解锁互斥锁的机会执行wakeAll()。线程 A 还没有等待,因此它会导致与原始场景相同的结果。
    • @doc no QWaitCondition 是专门设计的,因此在调用wait 时,在互斥锁解锁后调用的任何wake 都会唤醒调用wait 的线程。
    • 文档说互斥锁在等待之前被解锁,所以我很怀疑。我已经挖掘了源代码,似乎 wakeAll()/wakeOne()wait() 受到另一个互斥锁的保护,所以 +1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 2017-03-08
    • 1970-01-01
    相关资源
    最近更新 更多