Qt线程同步
来源:互联网 发布:知乎搞笑问题 编辑:程序博客网 时间:2024/05/22 05:17
多线程有的时候是很有用的,但是在访问一些公共的资源或者数据时,需要进行同步,否则会使数据遭到破坏或者获取的值不正确。Qt提供了一些类来实现线程的同步,如QMutex,QMutexLocker,QReadWriteLock,QReadLocker,QWriteLocker,QSemaphore和QWaitCondition。
QMutex 互斥量
QMutex ( RecursionMode mode = NonRecursive )。
RecursionMode 递归模式。枚举类型RecursionMode 有两个值:
QMutex::Recursive,在这个模式下,同一个线程可以多次锁同一个互斥量。需要注意的是,调用lock()多少次锁,就必须相应的调用unlock()一样次数解锁。
QMutex::NonRecursive(默认),在这个模式下,一个线程只能锁互斥量一次。
void QMutex::lock ()
该函数用来锁住一个互斥量。如果另外的线程已经锁住了互斥量,函数将被阻塞等待另外的线程解锁互斥量。
如果是一个可递归的互斥量,则可以从同一个线程多次调用这个函数,如果是非递归的互斥量,多次调用这个函数将会引发死锁。
bool QMutex::tryLock ()
该函数试图锁一个互斥量,如果成功则返回true。如果另外的线程已经锁住了互斥量,函数直接返回false,非阻塞。
void QMutex::unlock ()
该函数对互斥量进行解锁。如果在另外的线程加锁,尝试在别的线程进行解锁则会引发错误。试图对没有加锁的互斥量解锁结果是未定义的。
QMutexLocker(简化QMutex )
QmutexLocker只是为了简化我们队互斥量的加锁和解锁操作
QMutexLocker (QMutex * mutex )。
构造一个QMutexLocker对象并锁住互斥量。当QMutexLocker被销毁的时候,互斥量将被自动解锁。如果互斥量为0,QMutexLocker不起作用。
构造函数必须传入一个互斥量指针,在构造函数里mutex调用了lock()。
QMutex * QMutexLocker::mutex () const
返回在QMutexLocker构造函数中被锁定的互斥量
void QMutexLocker::relock ()
锁定一个解锁状态的互斥量
void QMutexLocker::unlock ()
解锁互斥量。你可以使用relock()再次锁定它。当销毁的时候互斥量不应该被锁定。
假设有个函数有很多return 语句,那么我们就必须记得在每个语句前unlock互斥量,否则互斥量将无法得到解锁,导致其他等待的线程无法继续执行。
int complexFunction(intflag) { mutex.lock(); int retVal = 0; switch (flag) { case 0: case1: 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
intcomplexFunction(int flag) { QMutexLocker locker(&mutex); 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; }
由于locker 是局部变量,在离开函数作用域时,mutex肯定会被解锁。
QreadWriteLock 读写锁
QreadWriteLock是一个读写锁,主要用来同步保护需要读写的资源。当你想多个读线程可以同时读取资源,但是只能有一个写线程操作资源,而其他线程必须等待写线程完成时,这时候用这个读写锁就很有用了。QreadWriteLock也有递归和非递归模式之分。
void QReadWriteLock::lockForRead ()
该函数lock加了读操作的锁。如果有别的线程已经对lock加了写操作的锁,则函数会阻塞等待。
void QReadWriteLock::lockForWrite ()
该函数给lock加了写操作的锁,如果别的线程已经加了读或者写的锁,则函数会被阻塞。
void QReadWriteLock::unlock ()
解锁函数。
QReadWriteLock lock;void ReaderThread::run(){ lock.lockForRead(); read_file(); lock.unlock(); }void WriterThread::run(){ lock.lockForWrite(); write_file(); lock.unlock();}
QReadLocker和QWriteLocker(简化QReadWriteLock)
当QReadLocker,QWriteLocker被销毁的时候,QReadWriteLock将被自动解锁。
QReadWriteLock lock ;QByteArray readData(){ lock.lockForRead(); ... lock.unlock(); return data;} //用下面的方式就可以简化了:QReadWriteLock lock ;QByteArray readData(){ QReadLocker locker(&lock); // ... return data;}
QSemaphore 信号量
QSemaphore是提供一个计数的信号量。信号量是泛化的互斥量。一个信号量只能锁一次,但是我们可以多次获得信号量。信号量可以用来同步保护一定数量的资源。
QSemaphore ( int n = 0 )
建立对象时可以给它n个资源
void acquire ( int n = 1 )
这个操作一次减少n个资源,如果现有资源不到n个就会阻塞
int available () const
返回当前可用的QSemaphore资源个数
void release ( int n = 1 )
这个操作一次增加n个资源
bool tryAcquire ( int n = 1 )
类似于acquire,但是申请不到n个资源时不会阻塞会立即返回
bool tryAcquire ( int n, int timeout )
类似于acquire,但是申请不到n个资源时会阻塞等待资源可用,阻塞超过 timeout毫秒就返回。
Example:
QSemaphore sem(5); // sem.available() == 5 sem.acquire(3); // sem.available() == 2 sem.acquire(2); // sem.available() == 0 sem.release(5); // sem.available() == 5 sem.release(5); // sem.available() == 10 sem.tryAcquire(1); // sem.available() == 9, returns true sem.tryAcquire(250); // sem.available() == 9, returns false
经典例子就是生产者-消费者
QWaitCondition 条件变量
QWaitCondition类提供了一个条件变量,它允许我们通知其他线程,等待的某些条件已经满足。等待QWaitCondition变量的可以是一个或多个线程。当我们用wakeOne()通知其他线程时,系统会随机的选中一个等待进行唤醒,让它继续运行。其实前面的信号量和读写锁内部实现都有用到QWaitCondition的。
QWaitCondition必须与QMutex或者QReadwriteLock一起用。
bool QWaitCondition::wait ( QMutex * mutex, unsigned long time =ULONG_MAX )
该函数对mutex解锁,然后等待。在调用这个函数之前,mutex必须是加锁状态。如果mutex没有加锁,则函数直接返回。如果mutex是可递归的,函数也直接返回。该函数对mutex解锁,然后等待,知道以下条件之一满足:
另外的线程调用wakeOne()或 wakeAll(),则该函数会返回true。
时间过了Time毫秒。如果time为ULONG_MAX(默认),则将会一直等待不会超时。如果超时则返回false。
bool QWaitCondition::wait ( QReadWriteLock * readWriteLock, unsigned long time =ULONG_MAX )
该函数对readWriteLock解锁并等待条件变量。在调用这个函数之前,readWriteLock必须是加锁状态的。如果不是加锁状态,则函数立即返回。readWriteLock必须不能是递归加锁的,否则将不能正确的解锁。返回的满足条件跟上面的函数一样。
void QWaitCondition::wakeAll ()
这将会唤醒所有等待QWaitCondition的线程。这些线程被唤醒的顺序依赖于操组系统的调度策略,并且不能被控制或预知。
void QWaitCondition::wakeOne ()
这将会唤醒所有等待QWaitCondition的线程中的一个线程。这个被唤醒的线程依赖于操组系统的调度策略,并且不能被控制或预知。
- Qt同步线程
- Qt之线程同步
- QT-线程同步
- QT QSemaphore 线程同步
- Qt之线程同步
- Qt之线程同步
- Qt线程同步
- QT 线程同步
- Qt线程同步小案例
- qt线程同步之信号量
- Qt 线程同步之 QWaitCondition
- Qt随笔之Qt线程同步
- qt 线程与ui线程同步
- qt 线程与ui线程同步
- QT线程(二)---线程同步
- QT使用线程以及线程同步
- QT线程(二)---线程同步
- QT使用线程以及线程同步 .
- pyChar之SyntaxError: Non-ASCII character问题
- SonarQube静态代码分析实战
- LeetCode
- JavaScript全栈学习笔记(一)
- 设计模式之状态模式
- Qt线程同步
- 生产者与消费者
- 快排的递归与非递归实现(二)
- 欢迎使用CSDN-markdown编辑器
- oracle_Grid Infrastructure 启动的五大问题
- Java枚举类回顾
- linux中lspci命令简介
- SmartSql = Dapper + MyBatis + Cache(Memory | Redis) + ZooKeeper + R/W Splitting + ......
- Xcode7查看iphone真机的应用程序文件