同步主线程和工作线程

Posted

技术标签:

【中文标题】同步主线程和工作线程【英文标题】:Synchronising main thread and worker thread 【发布时间】:2018-02-13 06:20:55 【问题描述】:

在 QT 中,我正在从主(GUI)线程创建一个工作线程来执行某个操作,该操作访问两个线程共享的资源。在 GUI 中的某些操作上,主线程必须操作资源。我尝试使用QMutex 锁定该特定资源。这个资源一直被工作线程使用,如何通知主线程呢? 尝试使用QWaitCondition,但它使应用程序崩溃。

还有其他选项可以通知和实现线程之间的同步吗? 附上代码sn-p。

void WorkerThread::IncrementCounter()

    qDebug() << "In Worker Thread IncrementCounter function" << endl;
    while(stop == false)
    
        mutex.lock();
        for(int i = 0; i < 100; i++)
        
            for(int j = 0; j < 100; j++)
            
                counter++;
            
        

        qDebug() << counter;
        mutex.unlock();
    
    qDebug() << "In Worker Thread Aborting " << endl;


//Manipulating the counter value by main thread.
void WorkerThread::setCounter(int value)

    waitCondition.wait(&mutex);
    counter = value;
    waitCondition.notify_one();

【问题讨论】:

一个由两个线程共享的资源 - 你真的需要这个吗,或者工作线程可以发出一个信号让主线程代表它访问资源?跨度> 看起来 waitCondition.wait 需要来自其他地方的通知才能真正释放它。不熟悉QWaitCondition,但如果它基于条件变量,通常等待会挂起,直到有人通知。我没有看到与 setCounter 中的等待相对应的通知。 【参考方案1】:

您使用的等待条件完全错误。 我敦促您阅读互斥锁和条件,也许看看some examples。

wait() 将阻止执行,直到 notify_one() 或 notify_all() 在某处被调用。这当然不会发生在您的代码中。 您不能 wait() 一行上的条件,然后期望接下来的两行包含唯一的唤醒呼叫时会被调用。

你想要的是在一个线程中 wait() 并在另一个线程中 notify_XXX()。

【讨论】:

【参考方案2】:

您可以在同一进程中使用共享内存。每个线程都可以在写入之前将其锁定,如下所示:

QSharedMemory *shared=new QSharedMemory("Test Shared Memory");

if(shared->create(1,QSharedMemory::ReadWrite))

    shared->lock();

    // Copy some data to it
    char *to = (char*)shared->data();
    const char *from = &dataBuffer;
    memcpy(to, from, dataSize);

    shared->unlock();

您还应该锁定它以供阅读。如果需要字符串,则读取字符串比编写字符串更容易,如果它们是零终止的。您需要将 .toLatin1() 转换为以零结尾的字符串,您可以获得字符串的大小。您可能会使用 shared->attach(); 获得多个线程可以读取的锁;但这更多是为了读取不同进程的共享内存..

您可以只使用它而不是静音。我认为,如果您尝试锁定它,而其他东西已经将其锁定,它将一直阻塞,直到其他进程将其解锁。

【讨论】:

以上是关于同步主线程和工作线程的主要内容,如果未能解决你的问题,请参考以下文章

laravel 队列 - 同步驱动程序如何工作?它是在单独的进程/线程还是主执行线程中执行?

多线程7---volatile关键字,刷新线程工作空间内存到主内存中去,即保持同步

java内存模型

java内存模型

构建和同步多线程游戏循环

主线程和子线程的同步控制