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

Put all database operations in a specific thread using Qt

本文关键字:一个 线程 Qt 数据库 操作 使用      更新时间:2023-10-16

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

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

您的问题是一个经典的并发数据分析问题。你试过使用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);可能会抛出异常,则可以使用此方法。在这种情况下,仅使用我编写的代码将无法解锁互斥锁,程序将达到死锁

在我提供的示例中,以下是如何使用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
}
  • 请注意,在同一个线程中调用lock()两次会产生未定义行为

  • 如果您要处理多线程,我建议您开始阅读有关多线程数据管理的内容。这是一本好书。

  • 如果你坚持使用Qt的东西,这里是同样的东西从Qt…QMutex .

  • 相关文章: