在Qt中,线程同步可以使用以下几种方式来实现:
一、互斥锁(QMutex)
互斥锁用于保护共享资源,确保在同一时间只有一个线程能够访问该资源。线程在访问共享资源之前需要获取互斥锁,使用完后再释放互斥锁,以确保同一时间只有一个线程在执行关键代码段。
1.创建QMutex对象:在需要进行线程同步的地方,首先创建一个QMutex对象。
QMutex mutex;
2.获取互斥锁:在访问共享资源之前,线程需要获取互斥锁。使用lock()
方法获取互斥锁。如果互斥锁已被其他线程占用,当前线程会被阻塞,直到互斥锁被释放。
mutex.lock();
3.访问共享资源:获取到互斥锁后,线程可以安全地访问共享资源。
// 访问共享资源的代码
4.释放互斥锁:在线程完成对共享资源的访问之后,需要释放互斥锁,以便其他线程可以获取到互斥锁进行访问
mutex.unlock();
完整示例如下:
数据写入线程:
1 class WriteThread : public QObject 2 { 3 Q_OBJECT 4 public: 5 explicit WriteThread(QQueue<int> *buffer, QMutex *locker); 6 7 public slots: 8 void on_start_write_thread(); 9 10 private: 11 QQueue<int> *m_buffer; 12 QMutex *m_locker; 13 };
1 WriteThread::WriteThread(QQueue<int> *buffer, QMutex *locker):m_buffer(buffer),m_locker(locker) 2 { 3 4 } 5 6 void WriteThread::on_start_write_thread() 7 { int num = 1; 8 while (true) { 9 QThread::msleep(2000); 10 11 m_locker->lock(); 12 m_buffer->enqueue(num++); 13 m_locker->unlock(); 14 } 15 }
数据读取线程:
1 class ReadThread : public QObject 2 { 3 Q_OBJECT 4 public: 5 explicit ReadThread(QQueue<int> *buffer, QMutex *locker); 6 7 public slots: 8 void on_start_read_thread(); 9 10 private: 11 QQueue<int> *m_buffer; 12 QMutex *m_locker; 13 };
1 ReadThread::ReadThread(QQueue<int> *buffer, QMutex *locker):m_buffer(buffer),m_locker(locker) 2 { 3 4 } 5 6 void ReadThread::on_start_read_thread() 7 { 8 while (true) { 9 if (m_buffer->isEmpty) { 10 continue; 11 } 12 m_locker->lock(); 13 int num = m_buffer->dequeue(); 14 qDebug() << num; 15 m_locker->unlock(); 16 } 17 18 }
线程执行:
1 MainWindow::MainWindow(QObject *parent) : QObject(parent) 2 { 3 m_write_thread = new WriteThread(&m_buffer, &m_locker); 4 m_move_write = new QThread(this); 5 m_write_thread->moveToThread(m_move_write); 6 connect(this, &MainWindow::start_write_thread, m_write_thread, &WriteThread::on_start_write_thread); 7 8 m_read_thread = new ReadThread(&m_buffer, &m_locker); 9 m_move_read = new QThread(this); 10 m_read_thread->moveToThread(m_move_read); 11 connect(this, &MainWindow::start_read_thread, m_read_thread, &ReadThread::on_start_read_thread); 12 } 13 14 void MainWindow::start_thread() 15 { 16 m_move_write->start(); 17 emit start_write_thread(); 18 19 m_move_read->start(); 20 emit start_read_thread(); 21 }
二、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();
完成示例如下:
将互斥锁换成读写锁即可
1 void WriteThread::on_start_write_thread() 2 { 3 int num = 1; 4 while (true) { 5 QThread::msleep(2000); 6 7 m_locker->lockForWrite(); 8 m_buffer->enqueue(num++); 9 m_locker->unlock(); 10 } 11 }
1 void ReadThread::on_start_read_thread() 2 { 3 while (true) { 4 if (m_buffer->isEmpty()) { 5 continue; 6 } 7 8 m_locker->lockForRead(); 9 int num = m_buffer->dequeue(); 10 qDebug() << num; 11 m_locker->unlock(); 12 } 13 }
三、QWaitCondition(等待条件)
QWaitCondition是Qt中用于线程同步的一种机制,它允许线程等待特定条件的发生,并在条件满足时被唤醒继续执行。QWaitCondition通常与QMutex一起使用,以提供更复杂的线程同步机制。
QWaitCondition的使用步骤如下:
1.创建QWaitCondition对象:在需要进行线程同步的地方,首先创建一个QWaitCondition对象。
QWaitCondition condition;
2.创建QMutex对象:为了保护条件的读写操作,创建一个QMutex对象。
QMutex mutex;
3.在等待条件的线程中等待:在线程需要等待特定条件的发生时,使用wait()
方法使线程进入等待状态。
1 mutex.lock(); 2 condition.wait(&mutex); 3 mutex.unlock();
在调用wait()
方法之前,需要先获取到互斥锁(QMutex)。这样可以确保线程在等待之前能够安全地访问和检查条件。
4.在其他线程中满足条件并唤醒等待线程:当某个条件满足时,通过wakeOne()
或wakeAll()
方法唤醒等待的线程。
1 mutex.lock(); 2 condition.wakeOne(); // 或者使用 condition.wakeAll(); 3 mutex.unlock();
完整示例如下:
1 ReadThread::ReadThread(QQueue<int> *buffer, QMutex *locker, QWaitCondition *wait_condition) 2 :m_buffer(buffer),m_locker(locker),m_wait_condition(wait_condition) 3 { 4 5 } 6 7 void ReadThread::on_start_read_thread() 8 { 9 while (true) { 10 m_locker->lock(); 11 //线程进入等待状态。 12 m_wait_condition->wait(m_locker); 13 //满足等待条件,继续执行 14 int num = m_buffer->dequeue(); 15 qDebug() << num; 16 m_locker->unlock(); 17 } 18 }
1 WriteThread::WriteThread(QQueue<int> *buffer, QMutex *locker, QWaitCondition *wait_condition) 2 :m_buffer(buffer),m_locker(locker),m_wait_condition(wait_condition) 3 { 4 5 } 6 7 void WriteThread::on_start_write_thread() 8 { 9 int num = 1; 10 while (true) { 11 QThread::msleep(2000); 12 13 m_locker->lock(); 14 m_buffer->enqueue(num++); 15 // 满足条件,唤醒等待线程 16 m_wait_condition->wakeOne(); // 或者使用 condition.wakeAll(); 17 m_locker->unlock(); 18 } 19 }
1 MainWindow::MainWindow(QObject *parent) : QObject(parent) 2 { 3 m_write_thread = new WriteThread(&m_buffer, &m_locker, &m_wait_condition); 4 m_move_write = new QThread(this); 5 m_write_thread->moveToThread(m_move_write); 6 connect(this, &MainWindow::start_write_thread, m_write_thread, &WriteThread::on_start_write_thread); 7 8 m_read_thread = new ReadThread(&m_buffer, &m_locker, &m_wait_condition); 9 m_move_read = new QThread(this); 10 m_read_thread->moveToThread(m_move_read); 11 connect(this, &MainWindow::start_read_thread, m_read_thread, &ReadThread::on_start_read_thread); 12 } 13 14 void MainWindow::start_thread() 15 { 16 m_move_write->start(); 17 emit start_write_thread(); 18 19 m_move_read->start(); 20 emit start_read_thread(); 21 }
标签:Qt,thread,buffer,QReadWriteLock,start,locker,线程,read,QMutex From: https://www.cnblogs.com/ybqjymy/p/17996935