m0_61770108 2024-05-21 11:15 采纳率: 13.5%
浏览 52
已结题

QT+sqlite如何实现在不同线程同时执行“读”和“写”的操作

QT+sqlite如何实现在不同线程同时执行“读”和“写”的操作
试验:建立两个线程test1和test2:在test1中写 在test2中读
实验一:
test1与test2使用同一个连接,同时进行写和读操作,程序崩溃

试验二:
分别在两个子线程建立连接,并执行SQL语句,源码如下:

img

img

结果程序崩溃

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-21 11:15
    关注

    引自免费微信小程序:皆我百晓生

    为了实现QT+SQLite在同一时间允许不同线程执行读写操作,你需要采取一些特定的方法来处理数据库连接。SQLite本身并不支持多线程并发读写,但在Qt中可以利用QSqLiteDriver的特性来实现。你需要创建一个单独的数据库实例并设置为共享模式,这样就可以让多个线程安全地访问它。

    以下是修改后的代码示例:

    首先,在主函数中初始化数据库连接:

    #include <QCoreApplication>
    #include <QDebug>
    #include <QThread>
    #include <QTimer>
    #include <QSqLiteDriver>
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        // 创建共享数据库连接
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "sharedConnection");
        db.setHostName(":memory:");
        db.setDatabaseName("");
        if (!db.open())
        {
            qDebug() << "Error opening shared database: " << db.lastError().text();
            return -1;
        }
    
        // 设置SQLite驱动为共享模式
        static_cast<QSqLiteDriver*>(db.driver())->setUsesSharedResources(true);
    
        // 启动测试线程
        Test1* test1 = new Test1(&db);
        QThread* thread1 = new QThread;
        test1->moveToThread(thread1);
        connect(thread1, &QThread::started, test1, &Test1::run);
        connect(test1, &QObject::destroyed, thread1, &QThread::quit);
        connect(thread1, &QThread::finished, thread1, &QThread::deleteLater);
        thread1->start();
    
        Test2* test2 = new Test2(&db);
        QThread* thread2 = new QThread;
        test2->moveToThread(thread2);
        connect(thread2, &QThread::started, test2, &Test2::run);
        connect(test2, &QObject::destroyed, thread2, &QThread::quit);
        connect(thread2, &QThread::finished, thread2, &QThread::deleteLater);
        thread2->start();
    
        return a.exec();
    }
    

    然后,更新你的Test1和Test2类中的代码,去掉关于打开和关闭数据库的部分,因为它们会干扰到共享数据库连接:

    test1.cpp

    class Test1 : public QObject
    {
        Q_OBJECT
    public:
        explicit Test1(QSqlDatabase* db, QObject *parent = nullptr)
        {
            this->db = db;
        }
        void run()
        {
            while (m_state)
            {
                DB::LOG Log;
                // ... (其他逻辑)
    
                QString sql = /* ... */;
    
                QSqlQuery query(*db);
                if (query.exec(sql))
                    qDebug() << "INSERT TRUE";
                else
                    qDebug() << __FUNCTION__ << __LINE__ << query.lastError();
            }
        }
    
    private:
        QSqlDatabase* db;
    };
    

    test2.cpp

    class Test2 : public QObject
    {
        Q_OBJECT
    public:
        explicit Test2(QSqlDatabase* db, QObject *parent = nullptr)
        {
            this->db = db;
        }
        void run()
        {
            while (m_state)
            {
                DB::LOG Log;
                // ... (其他逻辑)
    
                QString sql = /* ... */;
    
                QSqlQuery query(*db);
                query.exec(sql);
    
                // ... (处理查询结果的逻辑)
            }
        }
    
    private:
        QSqlDatabase* db;
    };
    

    通过这种方式,你可以实现一个共享的SQLite数据库连接,使得不同线程可以安全地执行读写操作。注意,尽管这样可以解决线程同步的问题,但仍然需要注意数据的一致性,比如使用事务来保护敏感操作,或者在读写操作之间添加适当的同步机制(例如信号槽、互斥锁等)。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 8月6日
  • 创建了问题 5月21日

悬赏问题

  • ¥15 Opencv(C++)异常
  • ¥15 VScode上配置C语言环境
  • ¥15 汇编语言没有主程序吗?
  • ¥15 这个函数为什么会爆内存
  • ¥15 无法装系统,grub成了顽固拦路虎
  • ¥15 springboot aop 应用启动异常
  • ¥15 matlab有关债券凸性久期的代码
  • ¥15 lvgl v8.2定时器提前到来
  • ¥15 qtcp 发送数据时偶尔会遇到发送数据失败?用的MSVC编译器(标签-qt|关键词-tcp)
  • ¥15 cam_lidar_calibration报错