QT+sqlite如何实现在不同线程同时执行“读”和“写”的操作
试验:建立两个线程test1和test2:在test1中写 在test2中读
实验一:
test1与test2使用同一个连接,同时进行写和读操作,程序崩溃
试验二:
分别在两个子线程建立连接,并执行SQL语句,源码如下:
结果程序崩溃
QT+sqlite如何实现在不同线程同时执行“读”和“写”的操作
试验:建立两个线程test1和test2:在test1中写 在test2中读
实验一:
test1与test2使用同一个连接,同时进行写和读操作,程序崩溃
试验二:
分别在两个子线程建立连接,并执行SQL语句,源码如下:
结果程序崩溃
引自免费微信小程序:皆我百晓生
为了实现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数据库连接,使得不同线程可以安全地执行读写操作。注意,尽管这样可以解决线程同步的问题,但仍然需要注意数据的一致性,比如使用事务来保护敏感操作,或者在读写操作之间添加适当的同步机制(例如信号槽、互斥锁等)。