使用Qt将所有数据库操作放在特定的线程中

时间:2016-09-03 07:45:07

标签: c++ multithreading qt

我有一个控制台应用程序,在超时信号之后,应该逐个元素地解析2D矩阵(15 * 1200)并将其插入到数据库中。由于操作非常耗时,因此我使用QConcurrent::run在新线程中执行插入操作。

但是,由于超时信号,一个线程可能在一个完成之前启动,因此可能会发生对数据库的多次访问。 作为解决方案,我试图在特定的 线程中缓冲所有数据库操作,换句话说,将特定线程分配给数据库类,但不知道如何这样做。

1 个答案:

答案 0 :(得分:2)

您的问题是经典的并发数据分析问题。您是否尝试过使用std::mutex?以下是您如何使用它:

您创建了一个可由所有相关线程访问的变量std::mutex(互斥=互斥)。

std::mutex myLock;

然后,让我们说处理数据的函数如下所示:

void processData(const Data& myData)
{
    ProcessedData d = parseData();
    insertToDatabase(d);
}

根据我的理解,您担心多个线程会同时调用insertToDatabase(d)。现在要解决这个问题,只需执行以下操作:

void processData(const Data& myData)
{
    ProcessedData d = parseData();
    myLock.lock();
    insertToDatabase(d);
    myLock.unlock();
}

现在有了这个,如果另一个线程试图访问同一个函数,它将阻塞,直到另一个所有其他线程完成。因此线程相互排除一起访问该呼叫。

有关此内容的更多信息:

注意事项:

  1. 此互斥锁对象必须与所有线程看到的相同,否则这是无用的。所以要么把它全局化(糟糕的想法,但会起作用),要么将它放在将要进行调用的类中。

  2. 互斥对象是不可复制的。因此,如果将它们包含在类中,则应该将互斥对象作为指针,或者应该重新实现该类的复制构造函数以防止复制该互斥锁,或者使用delete使您的类不可复制:

    class MyClass
    {
        //... stuff
        MyClass(const MyClass& src) = delete;
        //... other stuff
    };
    
  3. 使用std::mutex的方式更为方便,包括std::lock_guardstd::unique_lock,它们拥有互斥锁并为您执行锁定。如果您知道调用insertToDatabase(d);可能会抛出异常,那么这很好用。在这种情况下,仅使用我编写的代码将无法解锁互斥锁,程序将达到死锁

  4. 在我提供的示例中,您可以使用lock_guard

    void processData(const Data& myData)
    {
        ProcessedData d = parseData();
        std::lock_guard<std::mutex> guard(myLock);
        insertToDatabase(d);
        //it will unlock automatically at the end of this function, when the object "guard" is destroyed
    }
    
    1. 请注意,同一个帖子两次调用lock()未定义的行为

    2. 我上面所做的一切都是C ++ 11。

    3. 如果您要处理多个线程,我建议您开始阅读有关多个线程的数据管理。 This是一本好书。

    4. 如果你坚持使用Qt的东西,这里的问题与Qt相同...... QMutex