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

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

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

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

img

img

结果程序崩溃

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2024-05-21 11:16
    关注

    上午好☀️☀️☀️️
    本答案参考ChatGPT-3.5

    在QT+sqlite中,要实现在不同线程同时执行“读”和“写”的操作,需要注意以下几点:

    1. 每个线程必须单独持有一个数据库连接

    2. 不同的线程之间不能直接共享连接对象,否则会出现线程同步问题

    3. 对于多线程操作sqlite库,需要对sqlite进行加锁操作,可以使用QReadWriteLock(读写锁)来实现。

    解决方案如下:

    1. 在每个线程中,单独创建一个数据库连接:
    // test1线程中创建连接
    QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE", "connection1");
    db1.setDatabaseName("test.db");
    if (!db1.open()) {
        qDebug() << "can not open db1:" << db1.lastError();
        return;
    }
    
    // test2线程中创建连接
    QSqlDatabase db2 = QSqlDatabase::addDatabase("QSQLITE", "connection2");
    db2.setDatabaseName("test.db");
    if (!db2.open()) {
        qDebug() << "can not open db2:" << db2.lastError();
        return;
    }
    
    1. 在程序中使用QReadWriteLock加锁,保证线程安全:
    // 多线程读取数据时,加上读锁
    QReadLocker locker(&m_lock);
    // 执行查询操作
    QSqlQuery query(db);
    query.exec("SELECT * FROM tablename");
    while (query.next()) {
        // 读取查询结果
    }
    
    // 多线程写入数据时,加上写锁
    QWriteLocker locker(&m_lock);
    // 执行插入操作
    QSqlQuery query(db);
    query.exec("INSERT INTO tablename (col1, col2) VALUES (val1, val2)");
    
    1. 在线程结束时关闭连接,避免内存泄漏:
    // 关闭连接
    db.close();
    

    最终实现可以参考以下示例代码:

    // test1线程中写入数据
    void test1::run() {
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "connection1");
        db.setDatabaseName("test.db");
        if (!db.open()) {
            qDebug() << "can not open db1:" << db.lastError();
            return;
        }
    
        while (m_run) {
            // 加上写锁,保证线程安全
            QWriteLocker locker(&m_lock);
            QSqlQuery query(db);
            query.exec("INSERT INTO tablename (col1, col2) VALUES (val1, val2)");
    
            // 睡眠1秒
            QThread::msleep(1000);
        }
    
        db.close();
    }
    
    // test2线程中读取数据
    void test2::run() {
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "connection2");
        db.setDatabaseName("test.db");
        if (!db.open()) {
            qDebug() << "can not open db2:" << db.lastError();
            return;
        }
    
        while (m_run) {
            // 加上读锁,保证线程安全
            QReadLocker locker(&m_lock);
            QSqlQuery query(db);
            query.exec("SELECT * FROM tablename");
            while (query.next()) {
                // 读取查询结果
            }
    
            // 睡眠1秒
            QThread::msleep(1000);
        }
    
        db.close();
    }
    
    评论

报告相同问题?

问题事件

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