【问题标题】:Mutex unlock failure when trying to acquire a QSemaphore尝试获取 QSemaphore 时互斥锁解锁失败
【发布时间】:2017-01-04 09:44:17
【问题描述】:

我有一个带有 2 个 QThreads 的应用程序,它们的行为类似于下面的伪代码(信号量是 QSemaphore 类型):

Thread1 {
    print("about to wait on semaphore 1");
    sem1.acquire(1);
    print("finished waiting on semaphore 1");
    sem2.release(1);
}

Thread2 {
    print("signaling semaphore 1");
    sem1.release(1);
    print("about to wait on semaphore 2");
    sem2.acquire(1);
}

问题是当第一个信号量发出信号时第一个线程没有唤醒,即应用程序产生以下输出:

about to wait on semaphore 1
signaling semaphore 1
about to wait on semaphore 2

就是这样。第一个线程不再唤醒。

现在我更改第一个线程以执行以下操作:

Thread1 {
    print("about to wait on semaphore 1");
    while (!sem1.tryAcquire(1, 200));
    print("finished waiting on semaphore 1");
    sem2.release(1);
}

在这种情况下,第一个线程在尝试再次获取信号量之前最多休眠 200 毫秒。现在我收到以下错误:

QWaitCondition::wait(): mutex unlock failure: Invalid argument

应用程序不使用其他互斥锁或其他同步原语。可能是什么问题?

更新

我删除了信号量并将每个信号量替换为 QWaitCondition 和 QMutex,现在它工作得很好。我没有做任何其他更改,我仍然不知道为什么带有信号量的版本不正确。它们都被初始化为0。

【问题讨论】:

    标签: multithreading qt synchronization qthread


    【解决方案1】:

    您可能在其他地方做错了什么(例如,信号量初始化代码)。


    以下示例编译并运行 (gcc)。

    threads.h:

    #pragma once
    
    #include <QThread>
    
    class Thread1 : public QThread
    {
    protected:
        virtual void run();
    };
    
    class Thread2 : public QThread
    {
    protected:
        virtual void run();
    };
    

    threads.cpp:

    #include "threads.h"
    
    #include <QSemaphore>
    #include <iostream>
    
    namespace
    {
    QSemaphore sem1, sem2;
    }
    
    void Thread1::run()
    {
        std::cout << "about to wait on semaphore 1\n";
        sem1.acquire(1);
        //while (!sem1.tryAcquire(1, 200));     //works too
        std::cout << "finished waiting on semaphore 1\n";
        sem2.release(1);
    }
    
    void Thread2::run()
    {
        std::cout << "signaling semaphore 1\n";
        sem1.release(1);
        std::cout << "about to wait on semaphore 2\n";
        sem2.acquire(1);
    }
    

    ma​​in.cpp:

    #include "threads.h"
    #include <iostream>
    
    int main(int argc, char *argv[])
    {
        Thread1 t1;
        Thread2 t2;
        t1.start();
        t2.start();
        t1.wait();
        t2.wait();
        std::cout << "Success\n";
    }
    

    可能的输出:

    signaling semaphore 1
    about to wait on semaphore 2
    about to wait on semaphore 1
    finished waiting on semaphore 1
    Success
    

    【讨论】:

    • 提示:您的示例不需要使用&lt;iostream&gt;,也不需要使用多个文件。使用qDebug() &lt;&lt; "Success"; 并在main.cpp 中仅使用一个#include &lt;QtCore&gt;
    • @Kuba Ober threads.h 因为 moc 而存在,threads.cpp 用于在单独的翻译单元中本地化信号量。而且我更喜欢语言的标准库而不是 Qt 的实现(口味问题):-)
    • 我已经删除了信号量并用 QWaitCondition 和 QMutex 替换了每个信号量,现在它工作得很好。我没有做任何其他更改,我仍然不知道为什么带有信号量的版本不正确。它们都被初始化为 0。
    • 这两个QThread 派生类不需要Q_OBJECT 宏。但如果他们这样做了,您只需在 main.cpp 末尾添加 #include "main.moc"
    • 对,不是在这种情况下,修复它。谢谢@KubaOber
    猜你喜欢
    • 2018-05-23
    • 2021-05-24
    • 2012-12-13
    • 2012-12-25
    • 2022-07-31
    • 2017-11-21
    • 2010-11-22
    • 1970-01-01
    相关资源
    最近更新 更多