临安网站建设个人介绍网页设计报告

当前位置: 首页 > news >正文

临安网站建设,个人介绍网页设计报告,个人电脑做网站服务器网站,国内大的网站建设公司↵ 由于这节内容资料比较少#xff0c;所以以下内容总结自Qt官方文献#xff0c;在文章最后会给出相应链接。 线程的目的是允许并行运行#xff0c;但有时线程必须停止等待其他线程。例如#xff0c;如果两个线程尝试访问同一个变量#xff0c;这样的话结果是未定义的。强…  ↵ 由于这节内容资料比较少所以以下内容总结自Qt官方文献在文章最后会给出相应链接。  线程的目的是允许并行运行但有时线程必须停止等待其他线程。例如如果两个线程尝试访问同一个变量这样的话结果是未定义的。强制线程相互等待的原则成为互斥是一种保护共享资源的常用技术。 同步线程类 QMutex  互斥锁QReadWriteLock  读-写锁QSemaphore  信号量QWaitCondition 条件变量QMutex互斥锁 提供一个互斥锁在任何事件至多有一个线程可以获得mutex。如果一个线程尝试获得mutex而mutex已经锁住那么这个线程将会睡眠 QReadWriteLock  读-写锁 读-写锁于QMutex相似但它对共享数据进行访问的区分分为“读”“写”访问允许多个线程同时对数据进行“读”访问QReadWiteLock的并行度大于QMutex QSemaphore  信号量 QSemaphore是QMutex的概括可保护一定数量的相同资源。相比之下QMutex 只保护一种资源。信号量示例显示了信号量的典型应用同步对生产者和使用者之间循环缓冲区的访问 QWaitCondition 条件变量 QWaitCondition允许一个线程在一些条件满足时唤醒其他线程 不是通过强制执行互斥而是通过提供条件变量来同步线程。一个或多个线程可以被堵塞来等待一个QWaitCondition使用wakeOne()可以唤醒一个随机选取的等待的线程使用wakeAll可以唤醒所有正在等待的线程 QMutex QMutex通常和QMutexLocker一起使用才可以确保这可以轻松确保锁定和解锁的执行一致。 常用函数 isRecursive判断互斥锁是否为递归Qt 5.7引入lock锁定互斥锁如果另一个线程锁定了互斥锁则此调用将阻塞直到该线程解锁它tryLockint 尝试锁定互斥锁如果已获得锁则函数返回true 否则返回 false可以设置等待时间。如果获得锁则必须使用unlock解锁互斥锁这样才能在另一个线程才能成功锁定它。try_lock()尝试锁定互斥锁如果已获得锁则函数返回true 否则返回 false,提供此功能是为了与标准库概念兼容,等价于tryLockQt  5.8 引入try_lock_for() 尝试锁定互斥锁如果已获得锁则函数返回true 否则返回 false, 如果获得锁必须使用unlock解锁互斥锁 如果为递归互斥锁允许在同一线程的容易个互斥锁上多次调用该函数 如果此互斥锁是非递归互斥锁则在尝试递归锁定互斥锁时此函数将始终返回 false。Qt  5.8 引入 try_lock_until 尝试锁定互斥锁如果已获得锁则函数返回true 否则返回 false, 如果获得锁必须使用unlock解锁互斥锁 如果为递归互斥锁允许在同一线程的容易个互斥锁上多次调用该函数 如果此互斥锁是非递归互斥锁则在尝试递归锁定互斥锁时此函数将始终返回 false。Qt  5.8 引入 unlock解锁互斥锁。QMutexQMutexQMutex::RecursionMode mode) 创建一个互斥锁时可以设置模式 QMutex::Recursive在这种模式下线程可以多次锁定同一个互斥锁,并且在进行相应数量的 unlock 调用之前互斥锁不会被解锁QMutex::NonRecursive在此模式下线程只能锁定一次互斥锁互斥锁使用场景当一个变量同时被多个线程访问 int number10;void text() {number*2;number5; } void text1() {number10;number*3; } 正常调用 text和text1()的话 text() number2*1020525 text1() number251030*390 同时调用的话可能会发生以下情况 线程1调用text() number10*220; 线程2调用text1()现在text()的调用暂停 number201030 number30*390; 继续完成线程text() number90595 为了防止以上情况可以上个互斥锁使得调用完某个函数才能调用其他函数。 QMutex mutex;//互斥锁int number10void text() {mutex.lock();//上锁number*2;number5;mutex.unlock();//解锁
}void text1() {mutex.lock();//上锁number10;number*3;mutex.unlock();//解锁
}QMutexLocker类 QMutexLocker类是一个方便点的类可以简化锁定和解锁的互斥锁。 使用方法QMutexLocker应该在需要锁定QMutex的函数中创建创建一个QMutexLock时互斥锁被锁定。更加方便 函数 mutex(()返回正在运行的互斥锁relock重新锁定未锁定的互斥锁锁。unlock解锁此互斥锁使用QMutex的情况需要在分支中解锁互斥锁 int complexFunction(int flag) {mutex.lock();int retVal 0;switch (flag) {case 0:case 1:retVal moreComplexFunction(flag);break;case 2:{int status anotherFunction();if (status 0) {mutex.unlock();return -2;}retVal status flag;}break;default:if (flag 10) {mutex.unlock();return -1;}break;}mutex.unlock();return retVal; } QMutexLocker的使用 int complexFunction(int flag) {QMutexLocker locker(mutex);//创建一个QmutexLocker对象int retVal 0;switch (flag) {case 0:case 1:return moreComplexFunction(flag);case 2:{int status anotherFunction();if (status 0)return -2;retVal status flag;}break;default:if (flag 10)return -1;break;}return retVal; } 当函数执行完后QMutexLocker对象销毁时互斥锁会解锁就不用每个分支去解锁。 使用QMutexLocker::mutex()可以获取当前正在运行的互斥锁。  QReadWriteLock(读-写锁) 读写锁是一种同步工具用于保护可以访问以进行读取和写入的资源。如果要允许多个线程同时具有只读访问权限则这种类型的锁定很有用但是一旦一个线程想要写入资源就必须阻止所有其他线程直到写入完成。 函数 lockForRead锁定读取 如果另一个线程已锁定写入此函数将阻止当前线程。 如果线程已锁定写入则无法锁定读取。 lockForWrite 锁定写入 如果另一个线程包括当前线程已锁定以进行读取或写入则此函数将阻止当前线程 tryLockForRead尝试锁定以进行读取如果线程已锁定写入则无法锁定读取tryLockForWrite尝试锁定以进行写入如果线程已锁定以进行读取则无法锁定写入unlock解锁QReadWriteLock通常使用于经常读取数据可以多个线程同时读取数据。 QReadWriteLock lock;void ReaderThread::run() {…lock.lockForRead();read_file();lock.unlock();… }void WriterThread::run() {…lock.lockForWrite();write_file();lock.unlock();… } QSemaphore信号量 信号量是互斥锁的概括。虽然互斥锁只能锁定一次但可以多次获取信号量。信号量通常用于保护一定数量的相同资源 函数 acquireint n尝试获取n个由信号量保护的资源当资源不够时将堵塞直到资源足够。releaseint n 释放由信号量保护的 n 个资源 此函数也可用于“创建”资源。 available返回信号灯当前可用的资源数。这个数字永远不能是负数。tryAcquireint n尝试获取由信号量保护的资源成功返回true否则返回false tryAcquireint n,int timeout 尝试获取由信号量保护的资源成功返回true否则返回false调用最多等待timeout秒QSemaphore的创建 QSemaphore::QSemaphore(int n0)  创建新的信号量并将其保护的资源数初始化为 n默认为 0。 QSemaphore sem(5);sem.acquire(3);qDebug()资源还有sem.available()个;sem.acquire(2);qDebug()资源还有sem.available()个;sem.release(5);qDebug()资源还有sem.available()个; 当释放的资源多余需要释放的资源时多余的会进行创建 QSemaphore sem(5);sem.acquire(3);qDebug()资源还有sem.available()个;sem.release(5);qDebug()资源还有sem.available()个;sem.release(10);qDebug()资源还有sem.available()个;当资源少于需要获取的资源时不会获取成功。 QSemaphore sem(5);if(sem.tryAcquire(7)){qDebug()获取成功;}else{qDebug()获取失败;} QWaitCondition 允许一个线程在一些条件满足时唤醒其他线程 不是通过强制执行互斥而是通过提供条件变量来同步线程。一个或多个线程可以被堵塞来等待一个QWaitCondition使用wakeOne()可以唤醒一个随机选取的等待的线程使用wakeAll可以唤醒所有正在等待的线程 函数 wait(QMutex*time)释放锁定的互斥锁并等待等待条件wakeOne()唤醒一个等待等待条件的线程。唤醒的线程取决于操作系统的调度策略无法控制或预测。如果要唤醒特定线程解决方案通常是使用不同的等待条件并让不同的线程等待不同的条件wakeAll()唤醒等待等待条件的所有线程。线程的唤醒顺序取决于操作系统的调度策略无法控制或预测。notify_one() 提供此函数是为了与 STL 兼容。它等效于 wakeOneQt 5.8中引入 notify_all()提供此函数是为了与 STL 兼容。它等效于 wakeAllQt 5.8中引入QWaitCondition的示例 使用QWaitCondition的QMutex解决生产者-消费者问题 设置全局变量  const int DataSize 100000;//生产者将生成的数据量const int BufferSize 8192;//缓冲区 char buffer[BufferSize];//两个等待条件一个互斥锁和计数器 QWaitCondition bufferNotEmpty; QWaitCondition bufferNotFull; QMutex mutex; int numUsedBytes 0;生产者类 class Producer : public QThread { public:Producer(QObject *parent NULL) : QThread(parent){}void run() override{for (int i 0; i DataSize; i) {mutex.lock();//上锁if (numUsedBytes BufferSize)//检查缓冲区是否已满bufferNotFull.wait(mutex);//已满的话等待条件满足mutex.unlock();//解锁//存放数据(随机数)buffer[i % BufferSize] ACGT[QRandomGenerator::global()-bounded(4)];mutex.lock();//上锁numUsedBytes;计数器1bufferNotEmpty.wakeAll();//唤醒全部线程mutex.unlock();//解锁}} }; 消费者类 class Consumer : public QThread {Q_OBJECT public:Consumer(QObject *parent NULL) : QThread(parent){}void run() override{for (int i 0; i DataSize; i) {mutex.lock();if (numUsedBytes 0)//检查缓冲区是否为空bufferNotEmpty.wait(mutex);mutex.unlock();fprintf(stderr, %c, buffer[i % BufferSize]);//输出内容mutex.lock();–numUsedBytes;//计数器-1bufferNotFull.wakeAll();mutex.unlock();}fprintf(stderr, \n);}signals:void stringConsumed(const QString text); }; main函数 int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);Producer producer;//生产者Consumer consumer;//消费者producer.start();//开启线程consumer.start();//开启线程//两个线程调用wait()阻塞线程确保两个线程在退出前都有时间能完成main()producer.wait();consumer.wait();return 0; } QSemaphore信号量的生产者消费者问题。 全局变量
const int DataSize1000;//生产者的数据量 const int BufferSize800;//缓冲区大小 char buffer[Buffersize]; QSemaphore freeBytes(BufferSize);//控制缓冲区的信号量 QSemaphore usedBytes;//控制已经使用的缓冲区 生产者类 class Producer public QThread { public:void run(); }void Producer::run() {qsrand(QTime(0.0.0).secsTo(QTime::currentTime()));//随机数for(int i0;iDataSize;i){freeBytes.acquire();buffer[%BufferSize]ACGT[(int)qrand %4];qDebug()QString(Producer:%1).arg(buffer[i%buffersize]);usedBytes.release();} 消费者类 class Consumer public QThread { public:void run(); }void Producer::run() {for(int i0;iDataSize;i){userBytes.acquire();qDebug()QString(Producer:%1).arg(buffer[i%buffersize]);freeBytes.release();}} main int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);Producer producer;//生产者Consumer consumer;//消费者producer.start();//开启线程consumer.start();//开启线程//两个线程调用wait()阻塞线程确保两个线程在退出前都有时间能完成main()producer.wait();consumer.wait();return 0; } 参考文献 同步线程|Qt 5.15 QMutex 类 |Qt核心 5.15.12 QMutexLocker Class |Qt核心 5.15.12 QReadWriteLock 类 |Qt核心 5.15.12 QSemaphore Class | Qt Core 5.15.12 QWaitCondition Class | Qt Core 5.15.12