Qt之线程同步

发布时间 2023-05-29 11:30:48作者: TechNomad

在Qt中,线程同步可以使用以下几种方式来实现:

一、互斥锁(QMutex)

互斥锁用于保护共享资源,确保在同一时间只有一个线程能够访问该资源。线程在访问共享资源之前需要获取互斥锁,使用完后再释放互斥锁,以确保同一时间只有一个线程在执行关键代码段。

1.创建QMutex对象:在需要进行线程同步的地方,首先创建一个QMutex对象。

QMutex mutex;

2.获取互斥锁:在访问共享资源之前,线程需要获取互斥锁。使用lock()方法获取互斥锁。如果互斥锁已被其他线程占用,当前线程会被阻塞,直到互斥锁被释放。

mutex.lock();

3.访问共享资源:获取到互斥锁后,线程可以安全地访问共享资源。

// 访问共享资源的代码

4.释放互斥锁:在线程完成对共享资源的访问之后,需要释放互斥锁,以便其他线程可以获取到互斥锁进行访问

mutex.unlock();

完整示例如下:

数据写入线程:

class WriteThread : public QObject
{
    Q_OBJECT
public:
    explicit WriteThread(QQueue<int> *buffer, QMutex *locker);

public slots:
    void on_start_write_thread();

private:
    QQueue<int> *m_buffer;
    QMutex *m_locker;
};
WriteThread::WriteThread(QQueue<int> *buffer, QMutex *locker):m_buffer(buffer),m_locker(locker)
{

}

void WriteThread::on_start_write_thread()
{  
    while (true) {
        if (m_buffer->isEmpty()) {
            continue;
        }

        m_locker->lock();
        int num = m_buffer->dequeue();
        qDebug() << num;
        m_locker->unlock();
    }
}

数据读取线程:

class ReadThread : public QObject
{
    Q_OBJECT
public:
    explicit ReadThread(QQueue<int> *buffer, QMutex *locker);

public slots:
    void on_start_read_thread();

private:
    QQueue<int> *m_buffer;
    QMutex *m_locker;
};
ReadThread::ReadThread(QQueue<int> *buffer, QMutex *locker):m_buffer(buffer),m_locker(locker)
{

}

void ReadThread::on_start_read_thread()
{
   
}

线程执行:

MainWindow::MainWindow(QObject *parent) : QObject(parent)
{
    m_write_thread = new WriteThread(&m_buffer, &m_locker);
    m_move_write = new QThread(this);
    m_write_thread->moveToThread(m_move_write);
    connect(this, &MainWindow::start_write_thread, m_write_thread, &WriteThread::on_start_write_thread);

    m_read_thread = new ReadThread(&m_buffer, &m_locker);
    m_move_read = new QThread(this);
    m_read_thread->moveToThread(m_move_read);
    connect(this, &MainWindow::start_read_thread, m_read_thread, &ReadThread::on_start_read_thread);
}

void MainWindow::start_thread()
{
    m_move_write->start();
    emit start_write_thread();

    m_move_read->start();
    emit start_read_thread();
}

二、QReadWriteLock(读写锁)

读写锁是Qt中用于实现读写线程同步的一种机制。它提供了一种更高效的方式来管理对共享资源的读写操作,允许多个线程同时进行读操作,但只允许一个线程进行写操作。

QReadWriteLock的使用步骤如下:

1.创建QReadWriteLock对象:在需要进行读写线程同步的地方,首先创建一个QReadWriteLock对象。

QReadWriteLock rwLock;

2.获取读锁:当线程需要进行读操作时,使用lockForRead()方法获取读锁。多个线程可以同时获取读锁,以进行并发的读操作。

rwLock.lockForRead();

3.进行读操作:获取到读锁后,线程可以安全地进行读操作,访问共享资源

// 进行读操作的代码

4.释放读锁:在读操作完成后,使用unlock()方法释放读锁,允许其他线程获取读锁。

rwLock.unlock();

5.获取写锁:当线程需要进行写操作时,使用lockForWrite()方法获取写锁。写锁是独占的,只允许一个线程获取写锁进行写操作,其他线程需要等待写锁的释放。

rwLock.lockForWrite();

6.进行写操作:获取到写锁后,线程可以安全地进行写操作,修改共享资源。

// 进行写操作的代码

7.释放写锁:在写操作完成后,使用unlock()方法释放写锁,允许其他线程获取读锁或写锁。

rwLock.unlock();

完成示例如下:

将互斥锁换成读写锁即可

void WriteThread::on_start_write_thread()
{
    int num = 1;
    while (true) {
        QThread::msleep(2000);

        m_locker->lockForWrite();
        m_buffer->enqueue(num++);
        m_locker->unlock();
    }
}
void ReadThread::on_start_read_thread()
{
    while (true) {
        if (m_buffer->isEmpty()) {
            continue;
        }

        m_locker->lockForRead();
        int num = m_buffer->dequeue();
        qDebug() << num;
        m_locker->unlock();
    }
}